Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Batkovich
2016-07-05 10:06:07 +03:00
119 changed files with 1779 additions and 1166 deletions
@@ -1523,9 +1523,13 @@ public class BuildManager implements Disposable {
final CompilerConfiguration config = CompilerConfiguration.getInstance(project);
for (Module module : compileContext.getCompileScope().getAffectedModules()) {
if (config.getAnnotationProcessingConfiguration(module).isEnabled()) {
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
if (path != null) {
candidates.add(path);
final String productionPath = CompilerPaths.getAnnotationProcessorsGenerationPath(module, false);
if (productionPath != null) {
candidates.add(productionPath);
}
final String testsPath = CompilerPaths.getAnnotationProcessorsGenerationPath(module, true);
if (testsPath != null) {
candidates.add(testsPath);
}
}
}
@@ -71,7 +71,14 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
public BuilderMessageHandler unregisterBuildMessageHandler(UUID sessionId) {
myCanceledSessions.remove(sessionId);
final SessionData data = mySessionDescriptors.remove(sessionId);
return data != null? data.handler : null;
if (data == null) {
return null;
}
final Channel channel = data.channel;
if (channel != null) {
channel.attr(SESSION_DATA).remove(); // cleanup the attribute so that session data is not leaked
}
return data.handler;
}
public void cancelSession(UUID sessionId) {
@@ -176,10 +176,20 @@ public class CompilerPaths {
return outPathUrl != null? VirtualFileManager.extractPath(outPathUrl) : null;
}
/**
* @return path to annotation-processors generated _production_ sources
Use {@link #getAnnotationProcessorsGenerationPath(Module, boolean)}
*/
@Deprecated
@Nullable
public static String getAnnotationProcessorsGenerationPath(Module module) {
return getAnnotationProcessorsGenerationPath(module, false);
}
@Nullable
public static String getAnnotationProcessorsGenerationPath(Module module, boolean forTests) {
final AnnotationProcessingConfiguration config = CompilerConfiguration.getInstance(module.getProject()).getAnnotationProcessingConfiguration(module);
final String sourceDirName = config.getGeneratedSourcesDirectoryName(false);
final String sourceDirName = config.getGeneratedSourcesDirectoryName(forTests);
if (config.isOutputRelativeToContentRoot()) {
final String[] roots = ModuleRootManager.getInstance(module).getContentRootUrls();
if (roots.length == 0) {
@@ -192,7 +202,7 @@ public class CompilerPaths {
}
final String path = getModuleOutputPath(module, false);
final String path = getModuleOutputPath(module, forTests);
if (path == null) {
return null;
}
@@ -23,6 +23,7 @@ import org.jetbrains.org.objectweb.asm.*;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Arrays;
/**
* @author egor
@@ -35,26 +36,29 @@ public class MethodBytecodeUtil {
* Allows to use ASM MethodVisitor with jdi method bytecode
*/
public static void visit(ClassType classType, Method method, MethodVisitor methodVisitor) {
visit(classType, method, method.bytecodes(), methodVisitor);
}
public static void visit(ClassType classType, Method method, long maxOffset, MethodVisitor methodVisitor) {
visit(classType, method, Arrays.copyOf(method.bytecodes(), (int)maxOffset), methodVisitor);
}
private static void visit(ClassType classType, Method method, byte[] bytecodes, MethodVisitor methodVisitor) {
try {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos)) {
dos.writeInt(0xCAFEBABE); // magic
dos.writeInt(Opcodes.V1_8); // version
dos.writeShort(classType.constantPoolCount()); // constant_pool_count
dos.write(classType.constantPool()); // constant_pool
dos.writeShort(0); // access_flags;
dos.writeShort(0); // this_class;
dos.writeShort(0); // super_class;
dos.writeShort(0); // interfaces_count;
dos.writeShort(0); // fields_count;
dos.writeShort(0); // methods_count;
dos.writeShort(0); // attributes_count;
// we generate and put code attribute right after the constant pool
byte[] bytecodes = method.bytecodes();
int codeSize = dos.size();
dos.writeShort(0); // max_stack
dos.writeShort(0); // max_locals
dos.writeInt(bytecodes.length); // code_length
dos.write(bytecodes); // code
dos.writeShort(0); // exception_table_length
dos.writeShort(0); // attributes_count
codeSize = dos.size() - codeSize;
ClassReader clsReader = new ClassReader(bos.toByteArray());
ClassWriter clsWriter = new ClassWriter(clsReader, 0);
ClassWriter clsWriter = new ClassWriter(new ClassReader(bos.toByteArray()), 0);
clsWriter.visit(Opcodes.V1_8,
Opcodes.ACC_PUBLIC,
classType.name(),
@@ -62,11 +66,12 @@ public class MethodBytecodeUtil {
classType.superclass().name(),
classType.interfaces().stream().map(ReferenceType::name).toArray(String[]::new));
MethodVisitor mv = clsWriter.visitMethod(Opcodes.ACC_PUBLIC, method.name(), method.signature(), method.signature(), null);
mv.visitAttribute(createCode(clsReader, codeSize));
mv.visitAttribute(createCode(bytecodes));
new ClassReader(clsWriter.toByteArray()).accept(new ClassVisitor(Opcodes.ASM5) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
assert name.equals(method.name());
return methodVisitor;
}
}, 0);
@@ -76,13 +81,30 @@ public class MethodBytecodeUtil {
}
}
private static Attribute createCode(ClassReader cr, int len) {
return new Attribute("Code") {
@Override
public Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
return super.read(cr, off, len, buf, codeOff, labels);
}
}.read(cr, cr.header, len, null, 0, null);
}
private static Attribute createCode(byte[] bytecodes) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos)) {
dos.writeInt(0xCAFEBABE); // magic
dos.writeInt(Opcodes.V1_8); // version
dos.writeShort(0); // constant_pool_count
// we generate and put code attribute right after the constant pool
int codeSize = dos.size();
dos.writeShort(0); // max_stack
dos.writeShort(0); // max_locals
dos.writeInt(bytecodes.length); // code_length
dos.write(bytecodes); // code
dos.writeShort(0); // exception_table_length
dos.writeShort(0); // attributes_count
codeSize = dos.size() - codeSize;
ClassReader cr = new ClassReader(bos.toByteArray());
return new Attribute("Code") {
@Override
public Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
return super.read(cr, off, len, buf, codeOff, labels);
}
}.read(cr, cr.header, codeSize, null, 0, null);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -17,10 +17,12 @@ package com.intellij.debugger.ui;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.InputValidatorEx;
import com.intellij.openapi.ui.Messages;
import com.intellij.ui.classFilter.ClassFilter;
import com.intellij.ui.classFilter.ClassFilterEditor;
import com.intellij.util.IconUtil;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -35,7 +37,34 @@ public class InstanceFilterEditor extends ClassFilterEditor {
}
protected void addClassFilter() {
String idString = Messages.showInputDialog(myProject, DebuggerBundle.message("add.instance.filter.dialog.prompt"), DebuggerBundle.message("add.instance.filter.dialog.title"), Messages.getQuestionIcon());
String idString = Messages.showInputDialog(myProject,
DebuggerBundle.message("add.instance.filter.dialog.prompt"),
DebuggerBundle.message("add.instance.filter.dialog.title"),
Messages.getQuestionIcon(),
null,
new InputValidatorEx() {
@Nullable
@Override
public String getErrorText(String inputString) {
try {
//noinspection ResultOfMethodCallIgnored
Long.parseLong(inputString);
return null;
} catch (NumberFormatException e) {
return DebuggerBundle.message("add.instance.filter.dialog.error.numeric.value.expected");
}
}
@Override
public boolean checkInput(String inputString) {
return getErrorText(inputString) == null;
}
@Override
public boolean canClose(String inputString) {
return getErrorText(inputString) == null;
}
});
if (idString != null) {
ClassFilter filter = createFilter(idString);
myTableModel.addRow(filter);
@@ -60,14 +89,4 @@ public class InstanceFilterEditor extends ClassFilterEditor {
protected boolean addPatternButtonVisible() {
return false;
}
protected ClassFilter createFilter(String pattern) {
try {
Long.parseLong(pattern);
return super.createFilter(pattern);
} catch (NumberFormatException e) {
Messages.showMessageDialog(this, DebuggerBundle.message("add.instance.filter.dialog.error.numeric.value.expected"), DebuggerBundle.message("add.instance.filter.dialog.title"), Messages.getErrorIcon());
return null;
}
}
}
@@ -37,8 +37,8 @@ public interface RecentTestRunner {
}
void setMode(Mode mode);
void run(String url);
void run(RunnerAndConfigurationSettings configuration);
void run(RecentTestsPopupEntry entry);
}
class RecentTestRunnerImpl implements RecentTestRunner {
@@ -67,14 +67,33 @@ class RecentTestRunnerImpl implements RecentTestRunner {
}
@Override
public void run(RunnerAndConfigurationSettings configuration) {
public void run(RecentTestsPopupEntry entry) {
entry.accept(new TestEntryVisitor() {
@Override
public void visitTest(@NotNull SingleTestEntry test) {
run(test.getUrl());
}
@Override
public void visitSuite(@NotNull SuiteEntry suite) {
run(suite.getSuiteUrl());
}
@Override
public void visitRunConfiguration(@NotNull RunConfigurationEntry configuration) {
run(configuration.getRunSettings());
}
});
}
private void run(RunnerAndConfigurationSettings configuration) {
Executor executor = myCurrentAction == RUN ? DefaultRunExecutor.getRunExecutorInstance()
: DefaultDebugExecutor.getDebugExecutorInstance();
ProgramRunnerUtil.executeConfiguration(myProject, configuration, executor);
}
public void run(@NotNull String url) {
private void run(@NotNull String url) {
Location location = myTestLocator.getLocation(url);
if (location == null) {
return;
@@ -25,68 +25,61 @@ fun SuiteEntry.isMyTest(test: SingleTestEntry): Boolean {
return testName.startsWith(this.suiteName)
}
data class SingleTestInfo(val test: SingleTestEntry, val runConfigurationName: String)
class RecentTestsData {
private val runConfigurationSuites = hashMapOf<String, RunConfigurationEntry>()
private var unmatchedRunConfigurationTests = arrayListOf<SingleTestEntry>()
private val urlSuites = mutableListOf<SuiteEntry>()
private var unmatchedUrlTests = mutableListOf<SingleTestEntry>()
private var testsWithoutSuites = arrayListOf<SingleTestInfo>()
fun addSuite(url: String, magnitude: Magnitude, runDate: Date, runConfiguration: RunnerAndConfigurationSettings?) {
val suite = SuiteEntry(url, magnitude, runDate)
if (runConfiguration != null) {
addRunConfigurationSuite(suite, runConfiguration)
}
else {
addUrlSuite(suite)
}
fun addSuite(url: String, runDate: Date, runConfiguration: RunnerAndConfigurationSettings) {
val suite = SuiteEntry(url, runDate)
addRunConfigurationSuite(suite, runConfiguration)
}
fun addTest(url: String, magnitude: Magnitude, runDate: Date, runConfiguration: RunnerAndConfigurationSettings?) {
val test = SingleTestEntry(url, magnitude, runDate)
if (runConfiguration != null) {
addRunConfigurationTest(test, runConfiguration)
}
else {
addUrlTest(test)
}
fun addTest(url: String, magnitude: Magnitude, runDate: Date, runConfiguration: RunnerAndConfigurationSettings) {
val test = SingleTestEntry(url, runDate, magnitude)
addRunConfigurationTest(test, runConfiguration)
}
private fun addUrlSuite(suite: SuiteEntry) {
val suiteTests = unmatchedUrlTests.filter { suite.isMyTest(it) }
suiteTests.forEach { suite.addTest(it) }
unmatchedUrlTests = unmatchedUrlTests.filterTo(arrayListOf(), { !suite.isMyTest(it) })
urlSuites.add(suite)
}
private fun addRunConfigurationSuite(suite: SuiteEntry, config: RunnerAndConfigurationSettings) {
val suiteTests = unmatchedRunConfigurationTests.filter { suite.isMyTest(it) }
suiteTests.forEach { suite.addTest(it) }
moveSuiteTestsToSuite(suite, config)
unmatchedRunConfigurationTests = unmatchedRunConfigurationTests.filterTo(arrayListOf(), { !suite.isMyTest(it) })
val id = config.uniqueID
runConfigurationSuites[id]?.addSuite(suite) ?: runConfigurationSuites.put(id, RunConfigurationEntry(config, suite))
val entry = runConfigurationSuites[id]
if (entry != null) {
entry.addSuite(suite)
}
else {
runConfigurationSuites.put(id, RunConfigurationEntry(config, suite))
}
}
private fun addUrlTest(test: SingleTestEntry) {
findUrlSuite(test.url)?.addTest(test) ?: unmatchedUrlTests.add(test)
private fun moveSuiteTestsToSuite(suite: SuiteEntry, config: RunnerAndConfigurationSettings) {
val filteredTests = arrayListOf<SingleTestInfo>()
testsWithoutSuites.forEach {
if (suite.isMyTest(it.test) && config.name == it.runConfigurationName) {
suite.addTest(it.test)
}
else {
filteredTests.add(it)
}
}
testsWithoutSuites = filteredTests
}
private fun addRunConfigurationTest(test: SingleTestEntry, runConfiguration: RunnerAndConfigurationSettings) {
findRunConfigurationSuite(test.url, runConfiguration)?.addTest(test) ?: unmatchedRunConfigurationTests.add(test)
val suiteEntry = findRunConfigurationSuite(test.url, runConfiguration)
if (suiteEntry != null) {
suiteEntry.addTest(test)
}
else {
testsWithoutSuites.add(SingleTestInfo(test, runConfiguration.name))
}
}
private fun findUrlSuite(url: String) = urlSuites.find {
val testName = VirtualFileManager.extractPath(url)
testName.startsWith(it.suiteName)
}
private fun findRunConfigurationSuite(url: String, runConfiguration: RunnerAndConfigurationSettings): SuiteEntry? {
val pack: RunConfigurationEntry = runConfigurationSuites[runConfiguration.uniqueID] ?: return null
val testName = VirtualFileManager.extractPath(url)
@@ -99,28 +92,69 @@ class RecentTestsData {
return null
}
fun computeConfigurationSuites() = runConfigurationSuites.values
.fold(arrayListOf(), { total: List<SuiteEntry>, entry: RunConfigurationEntry -> total + entry.suites })
fun getTestsToShow(): List<RecentTestsPopupEntry> {
val allConfigurationSuites = computeConfigurationSuites()
unmatchedRunConfigurationTests.forEach {
val currentTest = it
allConfigurationSuites.find { it.isMyTest(currentTest) }?.addTest(currentTest)
val allConfigurations = runConfigurationSuites.values
val allSuites = allConfigurations.fold(arrayListOf<SuiteEntry>(), { list: List<SuiteEntry>, entry -> list + entry.suites })
testsWithoutSuites.forEach {
val info = it
allSuites.find { it.isMyTest(info.test) }?.let { info.test.suite = it }
}
unmatchedUrlTests.forEach {
val currentTest = it
urlSuites.find { it.isMyTest(currentTest) }?.addTest(currentTest)
}
val testsCollector = SingleTestCollector()
allConfigurations.forEach { it.accept(testsCollector) }
val failedTests = testsCollector.tests.filter { it.failed }
return (runConfigurationSuites.values + urlSuites)
.sortedByDescending { it.runDate }
.fold(listOf(), { popupList, currentEntry ->
popupList + currentEntry.getEntriesToShow()
})
val configsCollector = ConfigurationsCollector()
allConfigurations.forEach { it.accept(configsCollector) }
val passedConfigurations = configsCollector.entries.filter { !it.failed }
val entriesToShow = failedTests + passedConfigurations + testsWithoutSuites.map { it.test }.filter { it.suite != null && it.failed }
return entriesToShow.sortedByDescending { it.runDate }
}
}
class UrlsCollector: TestEntryVisitor() {
val urls = mutableListOf<String>()
override fun visitSuite(suite: SuiteEntry) {
urls.add(suite.suiteUrl)
suite.tests.forEach { urls.add(it.url) }
}
override fun visitRunConfiguration(configuration: RunConfigurationEntry) {
configuration.suites.forEach { visitSuite(it) }
}
}
class SingleTestCollector : TestEntryVisitor() {
val tests = mutableListOf<SingleTestEntry>()
override fun visitTest(test: SingleTestEntry) {
tests.add(test)
}
override fun visitSuite(suite: SuiteEntry) {
suite.tests.forEach { it.accept(this) }
}
override fun visitRunConfiguration(configuration: RunConfigurationEntry) {
configuration.suites.forEach { it.accept(this) }
}
}
class ConfigurationsCollector : TestEntryVisitor() {
val entries = mutableListOf<RecentTestsPopupEntry>()
override fun visitRunConfiguration(configuration: RunConfigurationEntry) {
entries.add(configuration)
}
override fun visitSuite(suite: SuiteEntry) {
entries.add(suite)
}
}
@@ -98,8 +98,12 @@ public class RecentTestsListProvider {
}
RunnerAndConfigurationSettings runConfiguration = myConfigurationProvider.getConfiguration(record);
if (runConfiguration == null) {
return;
}
if (TestLocator.isSuite(url)) {
data.addSuite(url, magnitude, record.date, runConfiguration);
data.addSuite(url, record.date, runConfiguration);
}
else {
data.addTest(url, magnitude, record.date, runConfiguration);
@@ -16,72 +16,76 @@
package com.intellij.testIntegration
import com.intellij.execution.RunnerAndConfigurationSettings
import com.intellij.execution.testframework.TestIconMapper
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude.*
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude.ERROR_INDEX
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude.FAILED_INDEX
import com.intellij.icons.AllIcons
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiElement
import java.util.*
import javax.swing.Icon
interface RecentTestsPopupEntry {
val runDate: Date
val magnitude: TestStateInfo.Magnitude
val icon: Icon?
val presentation: String
val testsUrls: List<String>
fun run(runner: RecentTestRunner)
open fun navigatableElement(locator: TestLocator): PsiElement? = null
val runDate: Date
fun getEntriesToShow(): List<RecentTestsPopupEntry>
val failed: Boolean
fun accept(visitor: TestEntryVisitor)
}
open class SingleTestEntry(val url: String,
override val magnitude: TestStateInfo.Magnitude,
override val runDate: Date) : RecentTestsPopupEntry
abstract class TestEntryVisitor {
open fun visitTest(test: SingleTestEntry) = Unit
open fun visitSuite(suite: SuiteEntry) = Unit
open fun visitRunConfiguration(configuration: RunConfigurationEntry) = Unit
}
class SingleTestEntry(val url: String,
override val runDate: Date,
private val magnitude: TestStateInfo.Magnitude) : RecentTestsPopupEntry
{
override val presentation = VirtualFileManager.extractPath(url)
override val testsUrls = listOf(url)
override fun run(runner: RecentTestRunner) {
runner.run(url)
override val icon = TestIconMapper.getIcon(magnitude)
override val failed = magnitude == ERROR_INDEX || magnitude == FAILED_INDEX
var suite: SuiteEntry? = null
override fun accept(visitor: TestEntryVisitor) {
visitor.visitTest(this)
}
override fun navigatableElement(locator: TestLocator) = locator.getLocation(url)?.psiElement
override fun getEntriesToShow(): List<RecentTestsPopupEntry> = listOf(this)
}
class SuiteEntry(url: String, magnitude: TestStateInfo.Magnitude, runDate: Date) : SingleTestEntry(url, magnitude, runDate) {
private val tests = hashSetOf<SingleTestEntry>()
override val testsUrls: List<String>
get() = tests.fold(listOf<String>(), { acc, testEntry -> acc + testEntry.testsUrls })
val suiteName = VirtualFileManager.extractPath(url)
val failedTests: List<SingleTestEntry>
get() = tests.filter { it.magnitude == FAILED_INDEX || it.magnitude == ERROR_INDEX }
fun addTest(info: SingleTestEntry) = tests.add(info)
class SuiteEntry(val suiteUrl: String, override val runDate: Date) : RecentTestsPopupEntry {
override val presentation = suiteName
override fun getEntriesToShow(): List<RecentTestsPopupEntry> {
val failed = failedTests
if (failed.size > 0) {
return failed.sortedByDescending { it.runDate } + this
val tests = hashSetOf<SingleTestEntry>()
val suiteName = VirtualFileManager.extractPath(suiteUrl)
var runConfiguration: RunConfigurationEntry? = null
override val presentation = VirtualFileManager.extractPath(suiteUrl)
override val icon = AllIcons.RunConfigurations.Junit
override val failed: Boolean
get() {
return tests.find { it.failed } != null
}
return listOf(this)
}
override val magnitude: TestStateInfo.Magnitude by lazy {
tests.find { it.magnitude != PASSED_INDEX && it.magnitude != COMPLETE_INDEX }?.magnitude ?: PASSED_INDEX
fun addTest(test: SingleTestEntry) {
tests.add(test)
test.suite = this
}
override fun accept(visitor: TestEntryVisitor) {
visitor.visitSuite(this)
}
}
@@ -93,34 +97,28 @@ class RunConfigurationEntry(val runSettings: RunnerAndConfigurationSettings, ini
addSuite(initial)
}
fun addSuite(s: SuiteEntry) = suites.add(s)
override val runDate: Date
get() {
return suites.minBy { it.runDate }!!.runDate
}
override val failed: Boolean
get() {
return suites.find { it.failed } != null
}
override val runDate = suites.map { it.runDate }.min()!!
override val magnitude: TestStateInfo.Magnitude by lazy {
suites.find { it.magnitude != PASSED_INDEX && it.magnitude != COMPLETE_INDEX }?.magnitude ?: PASSED_INDEX
fun addSuite(suite: SuiteEntry) {
suites.add(suite)
suite.runConfiguration = this
}
override val presentation = runSettings.name
override val testsUrls: List<String>
get() = suites.fold(listOf<String>(), { list, suite -> list + suite.testsUrls })
override fun run(runner: RecentTestRunner) {
runner.run(runSettings)
}
override val icon = AllIcons.RunConfigurations.Junit
override fun getEntriesToShow(): List<RecentTestsPopupEntry> {
if (suites.size == 1) {
return suites[0].getEntriesToShow()
}
return suites
.filter { it.failedTests.size > 0}
.sortedByDescending { it.runDate }
.fold(listOf<RecentTestsPopupEntry>(), { popupList, currentEntry ->
popupList + currentEntry.getEntriesToShow()
}) + this
override fun accept(visitor: TestEntryVisitor) {
visitor.visitRunConfiguration(this)
}
}
}
@@ -15,12 +15,13 @@
*/
package com.intellij.testIntegration
import com.intellij.execution.testframework.TestIconMapper
import com.intellij.icons.AllIcons
import com.intellij.openapi.keymap.MacKeymapUtil
import com.intellij.openapi.ui.popup.ListPopupStep
import com.intellij.openapi.ui.popup.PopupStep
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
import com.intellij.openapi.util.SystemInfo
import com.intellij.psi.PsiElement
import com.intellij.ui.popup.list.ListPopupImpl
import com.intellij.util.PsiNavigateUtil
import java.awt.event.ActionEvent
@@ -31,9 +32,7 @@ import javax.swing.KeyStroke
class RecentTestsListPopup(popupStep: ListPopupStep<RecentTestsPopupEntry>,
private val testRunner: RecentTestRunner,
private val locator: TestLocator)
: ListPopupImpl(popupStep)
{
private val locator: TestLocator) : ListPopupImpl(popupStep) {
init {
shiftReleased()
@@ -58,16 +57,36 @@ class RecentTestsListPopup(popupStep: ListPopupStep<RecentTestsPopupEntry>,
override fun actionPerformed(e: ActionEvent) {
val values = selectedValues
if (values.size == 1) {
val element = (values[0] as RecentTestsPopupEntry).navigatableElement(locator)
if (element != null) {
val entry = values[0] as RecentTestsPopupEntry
getElement(entry)?.let {
cancel()
PsiNavigateUtil.navigate(element)
PsiNavigateUtil.navigate(it)
}
}
}
})
}
private fun getElement(entry: RecentTestsPopupEntry): PsiElement? {
var element: PsiElement? = null
entry.accept(object : TestEntryVisitor() {
override fun visitTest(test: SingleTestEntry) {
element = locator.getLocation(test.url)?.psiElement
}
override fun visitSuite(suite: SuiteEntry) {
element = locator.getLocation(suite.suiteUrl)?.psiElement
}
override fun visitRunConfiguration(configuration: RunConfigurationEntry) {
if (configuration.suites.size == 1) {
visitSuite(configuration.suites[0])
}
}
})
return element
}
private fun shiftPressed() {
setCaption("Debug Recent Tests")
testRunner.setMode(RecentTestRunner.Mode.DEBUG)
@@ -80,22 +99,99 @@ class RecentTestsListPopup(popupStep: ListPopupStep<RecentTestsPopupEntry>,
}
class SelectTestStep(tests: List<RecentTestsPopupEntry>,
private val runner: RecentTestRunner)
: BaseListPopupStep<RecentTestsPopupEntry>("Debug Recent Tests", tests)
class SelectTestStep(title: String?,
tests: List<RecentTestsPopupEntry>,
private val runner: RecentTestRunner) : BaseListPopupStep<RecentTestsPopupEntry>(title, tests)
{
override fun getIconFor(value: RecentTestsPopupEntry): Icon? {
return TestIconMapper.getIcon(value.magnitude)
if (value is SingleTestEntry) {
return AllIcons.RunConfigurations.TestFailed
}
else {
return AllIcons.RunConfigurations.TestPassed
}
}
override fun getTextFor(value: RecentTestsPopupEntry) = value.presentation
override fun isSpeedSearchEnabled() = true
override fun hasSubstep(selectedValue: RecentTestsPopupEntry) = getConfigurations(selectedValue).isNotEmpty()
override fun onChosen(entry: RecentTestsPopupEntry, finalChoice: Boolean): PopupStep<RecentTestsPopupEntry>? {
entry.run(runner)
return null
if (finalChoice) {
runner.run(entry)
return null
}
val configurations = getConfigurations(entry)
return SelectConfigurationStep(configurations, runner)
}
private fun getConfigurations(entry: RecentTestsPopupEntry): List<RecentTestsPopupEntry> {
val items = mutableListOf<RecentTestsPopupEntry>()
entry.accept(object : TestEntryVisitor() {
override fun visitTest(test: SingleTestEntry) {
val suite = test.suite ?: return
val configuration = suite.runConfiguration
if (configuration == null) {
items.add(suite)
return
}
if (isSingleTestConfiguration(configuration)) {
items.add(suite)
return
}
items.add(configuration)
if (configuration.suites.size > 1) {
items.add(0, suite)
}
}
private fun isSingleTestConfiguration(configuration: RunConfigurationEntry): Boolean {
val suites = configuration.suites
return suites.size == 1 && suites[0].tests.size == 1
}
})
return items
}
}
class SelectConfigurationStep(private val items: List<RecentTestsPopupEntry>,
private val runner: RecentTestRunner)
: BaseListPopupStep<RecentTestsPopupEntry>(null, items)
{
override fun getTextFor(value: RecentTestsPopupEntry): String {
var presentation = value.presentation
value.accept(object : TestEntryVisitor() {
override fun visitSuite(suite: SuiteEntry) {
presentation = "[suite] " + presentation
}
override fun visitRunConfiguration(configuration: RunConfigurationEntry) {
presentation = "[configuration] " + presentation
}
})
return presentation
}
override fun getIconFor(value: RecentTestsPopupEntry?) = AllIcons.RunConfigurations.Junit
override fun onChosen(selectedValue: RecentTestsPopupEntry, finalChoice: Boolean): PopupStep<RecentTestsPopupEntry>? {
if (finalChoice) {
runner.run(selectedValue)
}
return null
}
}
@@ -22,7 +22,6 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.util.Time;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Date;
@@ -60,7 +59,7 @@ public class ShowRecentTests extends AnAction {
List<RecentTestsPopupEntry> entries = listProvider.getTestsToShow();
SelectTestStep selectStepTest = new SelectTestStep(entries, testRunner);
SelectTestStep selectStepTest = new SelectTestStep("Debug Recent Tests", entries, testRunner);
RecentTestsListPopup popup = new RecentTestsListPopup(selectStepTest, testRunner, testLocator);
popup.showCenteredInCurrentWindow(project);
@@ -69,9 +68,9 @@ public class ShowRecentTests extends AnAction {
}
private static void cleanDeadTests(List<RecentTestsPopupEntry> entries, TestLocator testLocator, TestStateStorage testStorage) {
List<String> urls = ContainerUtil.newArrayList();
entries.forEach((entry) -> urls.addAll(entry.getTestsUrls()));
ApplicationManager.getApplication().executeOnPooledThread(new DeadTestsCleaner(testStorage, urls, testLocator));
UrlsCollector collector = new UrlsCollector();
entries.forEach((e) -> e.accept(collector));
ApplicationManager.getApplication().executeOnPooledThread(new DeadTestsCleaner(testStorage, collector.getUrls(), testLocator));
}
}
@@ -29,10 +29,9 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.VariableSearchUtils;
import com.siyeh.ig.psiutils.DeclarationSearchUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -131,7 +130,7 @@ public class SimplifyBooleanExpressionFix extends LocalQuickFixOnPsiElement {
PsiElement parent = orig.getParent();
if (parent == null) return;
if (statement instanceof PsiBlockStatement && parent instanceof PsiCodeBlock &&
!VariableSearchUtils.containsConflictingDeclarations(((PsiBlockStatement)statement).getCodeBlock(), (PsiCodeBlock)parent)) {
!DeclarationSearchUtils.containsConflictingDeclarations(((PsiBlockStatement)statement).getCodeBlock(), (PsiCodeBlock)parent)) {
// See IDEADEV-24277
// Code block can only be inlined into another (parent) code block.
// Code blocks, which are if or loop statement branches should not be inlined.
@@ -37,7 +37,8 @@ public class MakeTypeGenericInspection extends BaseJavaBatchLocalInspectionTool
@Override
public void visitVariable(PsiVariable variable) {
super.visitVariable(variable);
if (variable.getTypeElement() != null) {
final PsiTypeElement variableTypeElement = variable.getTypeElement();
if (variableTypeElement != null) {
final PsiType type = getSuggestedType(variable);
if (type != null) {
final String typeText = type.getCanonicalText();
@@ -46,8 +47,8 @@ public class MakeTypeGenericInspection extends BaseJavaBatchLocalInspectionTool
final PsiElement beforeInitializer =
PsiTreeUtil.skipSiblingsBackward(variable.getInitializer(), PsiWhiteSpace.class, PsiComment.class);
final ProblemDescriptor descriptor =
holder.getManager().createProblemDescriptor(variable.getTypeElement(),
beforeInitializer != null ? beforeInitializer : variable.getTypeElement(),
holder.getManager().createProblemDescriptor(variableTypeElement,
beforeInitializer != null ? beforeInitializer : variableTypeElement,
message, ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
isOnTheFly, new MyLocalQuickFix(message));
holder.registerProblem(descriptor);
@@ -42,14 +42,14 @@ public class ReplaceIteratorForEachLoopWithIteratorForLoopFix implements Intenti
@NotNull
@Override
public String getText() {
return "Replace 'for each' loop with iterator 'for' loop";
return getFamilyName();
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return getText();
return "Replace 'for each' loop with iterator 'for' loop";
}
@Override
@@ -112,9 +112,11 @@ public class ReplaceIteratorForEachLoopWithIteratorForLoopFix implements Intenti
newForLoop = (PsiForStatement)styleManager.reformat(newForLoop);
if (forEachBody instanceof PsiBlockStatement) {
final PsiStatement[] statements = ((PsiBlockStatement)forEachBody).getCodeBlock().getStatements();
for (int i = statements.length - 1; i >= 0; i--) {
newBodyBlock.addAfter(statements[i], newFirstStatement);
final PsiCodeBlock bodyCodeBlock = ((PsiBlockStatement)forEachBody).getCodeBlock();
final PsiElement firstBodyElement = bodyCodeBlock.getFirstBodyElement();
final PsiElement lastBodyElement = bodyCodeBlock.getLastBodyElement();
if (firstBodyElement != null && lastBodyElement != null) {
newBodyBlock.addRangeAfter(firstBodyElement, lastBodyElement, newFirstStatement);
}
}
else if (forEachBody != null && !(forEachBody instanceof PsiEmptyStatement)) {
@@ -79,14 +79,14 @@ public class HierarchyServiceImpl extends HierarchyService {
}
private void loadUnits(BitSet files, int[] indexKeys, StubEnter stubEnter) {
FileBasedIndexImpl.IdValueProcessor<IndexTree.Unit> processor = new FileBasedIndexImpl.IdValueProcessor<IndexTree.Unit>() {
FileBasedIndexImpl.IdValueProcessor<SerializedUnit> processor = new FileBasedIndexImpl.IdValueProcessor<SerializedUnit>() {
final ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
int count = 0;
@Override
public boolean process(int fileId, IndexTree.Unit unit) {
public boolean process(int fileId, SerializedUnit unit) {
if (indicator != null && ++count % 128 == 0) indicator.checkCanceled();
if (files.get(fileId)) {
stubEnter.unitEnter(unit, fileId);
unit.readUnit(stubEnter, fileId);
}
return true;
}
@@ -15,10 +15,16 @@
*/
package com.intellij.psi.stubsHierarchy.impl;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.util.ArrayUtil;
import com.intellij.util.BitUtil;
import com.intellij.util.io.DataInputOutputUtil;
import org.jetbrains.annotations.NotNull;
public class Imports {
import java.io.DataOutput;
import java.io.IOException;
class Imports {
public final static long[] EMPTY_ARRAY = ArrayUtil.EMPTY_LONG_ARRAY;
public static final int onDemandMask = 1 << 29;
@@ -30,11 +36,7 @@ public class Imports {
return (int)(importMask >>> 32);
}
public static QualifiedName getFullName(long importMask, NameEnvironment nameEnvironment) {
return nameEnvironment.qualifiedName(getFullNameId(importMask));
}
private static int getFullNameId(long importMask) {
static int getFullNameId(long importMask) {
int fullNameId = (int)importMask;
fullNameId &= mask;
return fullNameId;
@@ -48,10 +50,52 @@ public class Imports {
return BitUtil.isSet(importMask, staticMask);
}
public static long mkImport(QualifiedName fullname, boolean importStatic, boolean onDemand, int alias) {
long lower = fullname.myId;
public static long mkImport(@QNameId int fullname, boolean importStatic, boolean onDemand, int alias) {
long lower = fullname;
if (importStatic) lower |= staticMask;
if (onDemand) lower |= onDemandMask;
return (((long)alias) << 32) | lower;
}
private final static int IS_STATIC = 1;
private final static int IS_ON_DEMAND = 2;
private final static int HAS_ALIAS = 4;
static void writeImports(@NotNull DataOutput out, IndexTree.Unit value) throws IOException {
DataInputOutputUtil.writeINT(out, value.imports.length);
for (IndexTree.Import anImport : value.imports) {
writeImport(out, anImport);
}
}
static long[] readImports(UnitInputStream in) throws IOException {
int importCount = DataInputOutputUtil.readINT(in);
long[] imports = importCount == 0 ? EMPTY_ARRAY : new long[importCount];
for (int i = 0; i < importCount; i++) {
imports[i] = readImport(in);
}
return imports;
}
private static void writeImport(@NotNull DataOutput out, IndexTree.Import anImport) throws IOException {
SerializedUnit.writeQualifiedName(out, anImport.myFullname);
boolean hasAlias = anImport.myAlias != 0;
int flags = 0;
flags = BitUtil.set(flags, IS_STATIC, anImport.myStaticImport);
flags = BitUtil.set(flags, IS_ON_DEMAND, anImport.myOnDemand);
flags = BitUtil.set(flags, HAS_ALIAS, hasAlias);
out.writeByte(flags);
if (hasAlias) {
out.writeInt(anImport.myAlias);
}
}
private static long readImport(UnitInputStream in) throws IOException {
int fullname = in.names.readQualifiedName(in);
int flags = in.readByte();
return mkImport(fullname,
BitUtil.isSet(flags, IS_STATIC), BitUtil.isSet(flags, IS_ON_DEMAND),
BitUtil.isSet(flags, HAS_ALIAS) ? in.readInt() : 0);
}
}
@@ -28,6 +28,7 @@ import com.intellij.psi.impl.java.stubs.*;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree.*;
import com.intellij.psi.impl.java.stubs.impl.PsiClassStubImpl;
import com.intellij.psi.impl.source.JavaFileElementType;
import com.intellij.psi.stubs.Stub;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubTree;
@@ -47,7 +48,7 @@ public class JavaStubIndexer extends StubHierarchyIndexer {
@Override
public int getVersion() {
return 0;
return JavaFileElementType.STUB_VERSION + 1;
}
@Override
@@ -95,10 +96,7 @@ public class JavaStubIndexer extends StubHierarchyIndexer {
@Nullable
private static Decl processMember(StubElement<?> el, Set<String> namesCache) {
if (el instanceof PsiClassStubImpl) {
PsiClassStubImpl classStub = (PsiClassStubImpl)el;
if (!classStub.isAnonymousInQualifiedNew()) {
return processClassDecl(classStub, namesCache);
}
return processClassDecl((PsiClassStubImpl)el, namesCache);
}
ArrayList<Decl> innerList = new ArrayList<Decl>();
for (StubElement childElement : el.getChildrenStubs()) {
@@ -146,6 +144,9 @@ public class JavaStubIndexer extends StubHierarchyIndexer {
}
int flags = translateFlags(classStub, accessModifiers);
if (classStub.isAnonymousInQualifiedNew()) {
flags |= IndexTree.SUPERS_UNRESOLVED;
}
String[] supers = superList.isEmpty() ? ArrayUtil.EMPTY_STRING_ARRAY : ArrayUtil.toStringArray(superList);
Decl[] inners = innerList.isEmpty() ? Decl.EMPTY_ARRAY : innerList.toArray(new Decl[innerList.size()]);
return new ClassDecl(classStub.id, flags, classStub.getName(), supers, inners);
@@ -16,60 +16,92 @@
package com.intellij.psi.stubsHierarchy.impl;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import org.jetbrains.annotations.Nullable;
import com.intellij.util.io.DataInputOutputUtil;
import gnu.trove.TIntArrayList;
import gnu.trove.TLongIntHashMap;
import java.util.Arrays;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class NameEnvironment extends UserDataHolderBase {
class NameEnvironment extends UserDataHolderBase {
public static final int OBJECT_NAME = IndexTree.hashIdentifier("Object");
public final QualifiedName empty;
public final QualifiedName java_lang;
public static final int NO_NAME = 0;
@QNameId public final int java_lang;
public final QualifiedName java_lang_Enum;
public final QualifiedName annotation;
public final NamesEnumerator myNamesEnumerator;
public final QualifiedName java_lang_annotation_Annotation;
public NameEnvironment() {
myNamesEnumerator = new NamesEnumerator();
empty = myNamesEnumerator.getFullName(new int[]{}, true);
java_lang = fromString("java.lang", true);
java_lang_Enum = fromString("java.lang.Enum", true);
annotation = fromString("java.lang.annotation.Annotation", true);
private final TIntArrayList mySuffixes = new TIntArrayList();
private final TIntArrayList myStems = new TIntArrayList();
private final TLongIntHashMap myConcatenations = new TLongIntHashMap();
NameEnvironment() {
mySuffixes.add(0);
myStems.add(0);
java_lang = fromString("java.lang");
java_lang_Enum = new QualifiedName(fromString(CommonClassNames.JAVA_LANG_ENUM));
java_lang_annotation_Annotation = new QualifiedName(fromString(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION));
}
@Nullable
public QualifiedName fromString(String s, boolean create) {
return myNamesEnumerator.getFullName(IndexTree.hashQualifiedName(s), create);
@QNameId
int fromString(String s) {
return internQualifiedName(IndexTree.hashQualifiedName(s));
}
public QualifiedName prefix(QualifiedName name) {
if (name.myComponents.length <= 1) {
return empty;
@QNameId int prefixId(@QNameId int nameId) {
return myStems.get(nameId);
}
@ShortName int shortName(@QNameId int id) {
return mySuffixes.get(id);
}
@QNameId int findExistingName(@QNameId int stemId, @ShortName int suffix) {
int existing = myConcatenations.get(pack(stemId, suffix));
return existing > 0 ? existing : -1;
}
@QNameId int internQualifiedName(@ShortName int[] qname) {
int id = 0;
for (int shortName : qname) {
id = qualifiedName(id, shortName);
}
return myNamesEnumerator.getFullName(Arrays.copyOf(name.myComponents, name.myComponents.length - 1), true);
return id;
}
public QualifiedName qualifiedName(int id) {
return myNamesEnumerator.qualifiedName(id);
/**
* @see SerializedUnit#writeQualifiedName(DataOutput, int[])
*/
@QNameId int readQualifiedName(DataInput in) throws IOException {
int id = 0;
int len = DataInputOutputUtil.readINT(in);
for (int i = 0; i < len; i++) {
id = qualifiedName(id, in.readInt());
}
return id;
}
public int shortName(QualifiedName name) {
int[] ids = name.myComponents;
return ids[ids.length - 1];
int memberQualifiedName(@QNameId int ownerName, @ShortName int name) {
return name == NO_NAME || ownerName < 0 ? -1 : qualifiedName(ownerName, name);
}
public QualifiedName qualifiedName(QualifiedName prefix, int shortName, boolean create) {
if (shortName == NamesEnumerator.NO_NAME)
return null;
if (prefix == null || prefix.isEmpty())
return myNamesEnumerator.getFullName(new int[]{shortName}, create);
int[] ids = Arrays.copyOf(prefix.myComponents, prefix.myComponents.length + 1);
ids[ids.length - 1] = shortName;
return myNamesEnumerator.getFullName(ids, create);
@QNameId int qualifiedName(@QNameId int prefix, @ShortName int shortName) {
int existing = findExistingName(prefix, shortName);
return existing >= 0 ? existing : addName(prefix, shortName);
}
QualifiedName concat(int[] ids, boolean create) {
return myNamesEnumerator.getFullName(ids, create);
private int addName(@QNameId int stemId, @ShortName int suffix) {
int newId = mySuffixes.size();
mySuffixes.add(suffix);
myStems.add(stemId);
myConcatenations.put(pack(stemId, suffix), newId);
return newId;
}
private static long pack(@QNameId int stemId, @ShortName int suffix) {
return ((long)suffix << 32) + stemId;
}
}
@@ -1,70 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.stubsHierarchy.impl;
import gnu.trove.TObjectHashingStrategy;
import gnu.trove.TObjectIntHashMap;
import java.util.Arrays;
public class NamesEnumerator {
final static int NO_NAME = 0;
private final TObjectIntHashMap<int[]> myFullNameMap = new TObjectIntHashMap<int[]>(new TObjectHashingStrategy<int[]>() {
@Override
public int computeHashCode(int[] object) {
return Arrays.hashCode(object);
}
@Override
public boolean equals(int[] o1, int[] o2) {
return Arrays.equals(o1, o2);
}
});
private QualifiedName[] myQualifiedNames = new QualifiedName[0x8000];
QualifiedName qualifiedName(int id) {
return myQualifiedNames[id];
}
public QualifiedName getFullName(int[] ids, boolean create) {
int id = myFullNameMap.get(ids);
if (id == 0 && create) {
id = myFullNameMap.size() + 1;
myFullNameMap.put(ids, id);
ensureFullCapacity(id);
myQualifiedNames[id] = new QualifiedName(id, ids);
}
return myQualifiedNames[id];
}
private void ensureFullCapacity(int maxIndex) {
if (maxIndex >= myQualifiedNames.length) {
int newLength = calculateNewLength(myQualifiedNames.length, maxIndex);
QualifiedName[] names1 = new QualifiedName[newLength];
System.arraycopy(myQualifiedNames, 0, names1, 0, myQualifiedNames.length);
myQualifiedNames = names1;
}
}
private static int calculateNewLength(int currentLength, int maxIndex) {
while (currentLength < maxIndex + 1)
currentLength *= 2;
return currentLength;
}
}
@@ -15,33 +15,21 @@
*/
package com.intellij.psi.stubsHierarchy.impl;
import java.util.Arrays;
public final class QualifiedName {
public static final QualifiedName[] EMPTY_ARRAY = new QualifiedName[0];
// unique id of this full name
final class QualifiedName {
public final int myId;
// ids of parts of this name
public final int[] myComponents;
QualifiedName(int id, int[] components) {
QualifiedName(int id) {
this.myId = id;
this.myComponents = components;
}
public boolean isEmpty() {
return myComponents.length == 0;
return myId == 0;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof QualifiedName) {
QualifiedName other = (QualifiedName)o;
return myId == other.myId && Arrays.equals(myComponents, other.myComponents);
}
return false;
return o instanceof QualifiedName && myId == ((QualifiedName)o).myId;
}
@Override
@@ -0,0 +1,217 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.stubsHierarchy.impl;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.psi.stubsHierarchy.impl.Symbol.ClassSymbol;
import com.intellij.psi.stubsHierarchy.impl.Symbol.MemberSymbol;
import com.intellij.psi.stubsHierarchy.impl.Symbol.PackageSymbol;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.DataInputOutputUtil;
import com.intellij.util.io.DataOutputStream;
import com.intellij.util.io.UnsyncByteArrayInputStream;
import com.intellij.util.io.UnsyncByteArrayOutputStream;
import org.jetbrains.annotations.NotNull;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author peter
*/
class SerializedUnit {
private final byte[] myBytes;
SerializedUnit(byte[] bytes) {
myBytes = bytes;
}
SerializedUnit(IndexTree.Unit unit) {
try {
//noinspection IOResourceOpenedButNotSafelyClosed
UnsyncByteArrayOutputStream stream = new UnsyncByteArrayOutputStream();
writeUnit(new DataOutputStream(stream), unit);
myBytes = stream.toByteArray();
}
catch (IOException impossible) {
throw new RuntimeException(impossible);
}
}
byte[] getSerializedBytes() {
return myBytes;
}
void readUnit(StubEnter stubEnter, int fileId) {
try {
enterUnit(new UnitInputStream(new UnsyncByteArrayInputStream(myBytes), fileId, stubEnter));
}
catch (IOException impossible) {
throw new RuntimeException(impossible);
}
}
/**
* @see NameEnvironment#readQualifiedName(DataInput)
*/
static void writeQualifiedName(DataOutput out, @QNameId int[] array) throws IOException {
DataInputOutputUtil.writeINT(out, array.length);
for (int i : array) {
out.writeInt(i);
}
}
// unit
private static void writeUnit(@NotNull DataOutput out, IndexTree.Unit value) throws IOException {
writeQualifiedName(out, value.myPackageName);
out.writeByte(value.myUnitType);
if (value.myUnitType != IndexTree.BYTECODE) {
Imports.writeImports(out, value);
}
// class Declaration
DataInputOutputUtil.writeINT(out, value.myDecls.length);
for (IndexTree.ClassDecl def : value.myDecls) {
saveClassDecl(out, def);
}
}
private static void enterUnit(UnitInputStream in) throws IOException {
PackageSymbol pkg = in.stubEnter.enterPackage(in);
byte type = in.readByte();
long[] imports = type == IndexTree.BYTECODE ? Imports.EMPTY_ARRAY : Imports.readImports(in);
UnitInfo unitInfo = UnitInfo.mkUnitInfo(type, imports);
int classCount = DataInputOutputUtil.readINT(in);
for (int i = 0; i < classCount; i++) {
readClassDecl(in, unitInfo, pkg, pkg.myQualifiedName);
}
}
// class
private static void saveClassDecl(@NotNull DataOutput out, IndexTree.ClassDecl value) throws IOException {
DataInputOutputUtil.writeINT(out, value.myStubId);
DataInputOutputUtil.writeINT(out, value.myMods);
out.writeInt(value.myName);
writeSupers(out, value);
writeMembers(out, value.myDecls);
}
private static ClassSymbol readClassDecl(UnitInputStream in, UnitInfo info, Symbol owner, @QNameId int ownerName) throws IOException {
int stubId = DataInputOutputUtil.readINT(in);
int mods = DataInputOutputUtil.readINT(in);
@ShortName int name = in.readInt();
@QNameId int[] superNames = readSupers(in);
@QNameId int qname = in.names.memberQualifiedName(ownerName, name);
ClassSymbol symbol = in.stubEnter.classEnter(info, owner, stubId, mods, name, superNames, qname, in.fileId);
readMembers(in, info, qname, symbol);
return symbol;
}
// supers
private static void writeSupers(@NotNull DataOutput out, IndexTree.ClassDecl value) throws IOException {
DataInputOutputUtil.writeINT(out, value.mySupers.length);
for (int[] aSuper : value.mySupers) {
writeQualifiedName(out, aSuper);
}
}
private static @QNameId int[] readSupers(UnitInputStream in) throws IOException {
@QNameId int[] superNames = new int[DataInputOutputUtil.readINT(in)];
for (int i = 0; i < superNames.length; i++) {
superNames[i] = in.names.readQualifiedName(in);
}
return superNames;
}
// members
private static void writeMembers(@NotNull DataOutput out, IndexTree.Decl[] decls) throws IOException {
DataInputOutputUtil.writeINT(out, decls.length);
for (IndexTree.Decl def : decls) {
saveDecl(out, def);
}
}
private static void readMembers(UnitInputStream in,
UnitInfo info,
@QNameId int ownerName,
MemberSymbol symbol) throws IOException {
int memberCount = DataInputOutputUtil.readINT(in);
if (memberCount == 0) return;
List<ClassSymbol> members = new ArrayList<>();
for (int i = 0; i < memberCount; i++) {
ContainerUtil.addIfNotNull(members, readDecl(in, info, symbol, ownerName));
}
symbol.setMembers(members);
}
// decl: class or member
private static void saveDecl(@NotNull DataOutput out, IndexTree.Decl value) throws IOException {
if (value instanceof IndexTree.ClassDecl) {
out.writeBoolean(true);
saveClassDecl(out, (IndexTree.ClassDecl)value);
} else if (value instanceof IndexTree.MemberDecl) {
out.writeBoolean(false);
writeMembers(out, ((IndexTree.MemberDecl)value).myDecls);
}
}
private static ClassSymbol readDecl(UnitInputStream in, UnitInfo info, Symbol owner, @QNameId int ownerName) throws IOException {
if (in.readBoolean()) {
return readClassDecl(in, info, owner, ownerName);
}
readMembers(in, info, ownerName, new MemberSymbol(owner));
return null;
}
@Override
public boolean equals(Object o) {
return this == o || o instanceof SerializedUnit && Arrays.equals(myBytes, ((SerializedUnit)o).myBytes);
}
@Override
public int hashCode() {
int result = myBytes.length;
int length = Math.min(30, myBytes.length);
for (int i = 0; i < length; i++) {
result = 31 * result + myBytes[i];
}
return result;
}
}
class UnitInputStream extends DataInputStream {
final int fileId;
final StubEnter stubEnter;
final NameEnvironment names;
UnitInputStream(InputStream in, int fileId, StubEnter stubEnter) {
super(in);
this.fileId = fileId;
this.stubEnter = stubEnter;
this.names = stubEnter.myNameEnvironment;
}
}
@@ -26,6 +26,7 @@ import com.intellij.psi.stubsHierarchy.impl.Symbol.ClassSymbol;
import com.intellij.util.containers.ContainerUtil;
import org.apache.commons.lang.ArrayUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.BitSet;
@@ -71,7 +72,7 @@ public class SingleClassHierarchy extends ClassHierarchy {
private static BitSet calcAnonymous(ClassSymbol[] classSymbols) {
BitSet answer = new BitSet();
for (ClassSymbol symbol : classSymbols) {
if (!symbol.isHierarchyIncomplete() && symbol.myShortName == NamesEnumerator.NO_NAME) {
if (!symbol.isHierarchyIncomplete() && symbol.myShortName == NameEnvironment.NO_NAME) {
answer.set(symbol.myAnchorId);
}
}
@@ -112,13 +113,17 @@ public class SingleClassHierarchy extends ClassHierarchy {
@NotNull
@Override
public SmartClassAnchor[] getDirectSubtypeCandidates(@NotNull PsiClass psiClass) {
VirtualFile vFile = psiClass.getContainingFile().getVirtualFile();
if (!(vFile instanceof VirtualFileWithId)) return StubClassAnchor.EMPTY_ARRAY;
SmartClassAnchor anchor = forPsiClass(((VirtualFileWithId)vFile).getId(), psiClass);
SmartClassAnchor anchor = findAnchor(psiClass);
return anchor == null ? StubClassAnchor.EMPTY_ARRAY : getDirectSubtypeCandidates(anchor);
}
@Override
@Nullable
public SmartClassAnchor findAnchor(@NotNull PsiClass psiClass) {
VirtualFile vFile = psiClass.getContainingFile().getVirtualFile();
return vFile instanceof VirtualFileWithId ? forPsiClass(((VirtualFileWithId)vFile).getId(), psiClass) : null;
}
@NotNull
@Override
public SmartClassAnchor[] getDirectSubtypeCandidates(@NotNull SmartClassAnchor anchor) {
@@ -19,13 +19,15 @@ import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.util.BitUtil;
import org.jetbrains.annotations.Nullable;
import java.io.DataInput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import static com.intellij.psi.stubsHierarchy.impl.Symbol.*;
import static com.intellij.psi.stubsHierarchy.impl.Symbol.ClassSymbol;
import static com.intellij.psi.stubsHierarchy.impl.Symbol.PackageSymbol;
public class StubEnter {
private final NameEnvironment myNameEnvironment;
final NameEnvironment myNameEnvironment;
private final Symbols mySymbols;
private final StubHierarchyConnector myStubHierarchyConnector;
@@ -37,92 +39,32 @@ public class StubEnter {
myStubHierarchyConnector = new StubHierarchyConnector(myNameEnvironment, symbols);
}
void unitEnter(IndexTree.Unit unit, int fileId) {
PackageSymbol pkg = unit.myPackageName.length > 0
? mySymbols.enterPackage(myNameEnvironment.myNamesEnumerator.getFullName(unit.myPackageName, true))
: mySymbols.myRootPackage;
enter(unit.myDecls, UnitInfo.mkUnitInfo(unit.myUnitType, internImports(unit)), pkg, pkg.myQualifiedName, fileId);
PackageSymbol enterPackage(DataInput in) throws IOException {
return mySymbols.enterPackage(myNameEnvironment.readQualifiedName(in));
}
private long[] internImports(IndexTree.Unit unit) {
long[] imports = unit.imports.length == 0 ? Imports.EMPTY_ARRAY : new long[unit.imports.length];
for (int i = 0; i < unit.imports.length; i++) {
imports[i] = processImport(unit.imports[i]);
}
return imports;
}
private long processImport(IndexTree.Import anImport) {
QualifiedName fullname = myNameEnvironment.myNamesEnumerator.getFullName(anImport.myFullname, true);
return Imports.mkImport(fullname, anImport.myStaticImport, anImport.myOnDemand, anImport.myAlias);
}
private void enter(IndexTree.ClassDecl[] trees, UnitInfo info, Symbol owner, @Nullable QualifiedName ownerName, int fileId) {
for (IndexTree.ClassDecl tree : trees) {
enter(tree, info, owner, ownerName, fileId);
}
}
private ClassSymbol[] enter(IndexTree.Decl[] trees, UnitInfo info, Symbol owner, @Nullable QualifiedName ownerName, int fileId) {
ClassSymbol[] members = new ClassSymbol[trees.length];
int i = 0;
for (IndexTree.Decl tree : trees) {
ClassSymbol member = enter(tree, info, owner, ownerName, fileId);
if (member != null && member.myShortName != 0) {
members[i++] = member;
}
}
if (i == 0) return ClassSymbol.EMPTY_ARRAY;
if (i < members.length) {
members = Arrays.copyOf(members, i);
}
Arrays.sort(members, CLASS_SYMBOL_BY_NAME_COMPARATOR);
return members;
}
private ClassSymbol enter(IndexTree.Decl tree, UnitInfo info, Symbol owner, QualifiedName ownerName, int fileId) {
if (tree instanceof IndexTree.ClassDecl) {
return classEnter((IndexTree.ClassDecl)tree, info, owner, ownerName, fileId);
}
if (tree instanceof IndexTree.MemberDecl) {
memberEnter((IndexTree.MemberDecl)tree, info, owner, ownerName, fileId);
return null;
}
return null;
}
private void memberEnter(IndexTree.MemberDecl tree, UnitInfo info, Symbol owner, @Nullable QualifiedName ownerName, int fileId) {
MemberSymbol mc = new MemberSymbol(owner);
mc.setMembers(enter(tree.myDecls, info, mc, ownerName, fileId));
}
private ClassSymbol classEnter(IndexTree.ClassDecl tree, UnitInfo info, Symbol owner, @Nullable QualifiedName ownerName, int fileId) {
int flags = checkFlags(tree.myMods, owner);
if (info.getType() == IndexTree.BYTECODE) {
flags |= IndexTree.COMPILED;
}
int name = tree.myName;
QualifiedName qname = name == NamesEnumerator.NO_NAME || ownerName == null ? null
: myNameEnvironment.qualifiedName(ownerName, name, true);
@CompactArray(QualifiedName.class) Object supers = internSupers(tree.myMods, tree.mySupers);
ClassSymbol classSymbol = mySymbols.enterClass(fileId, tree.myStubId, flags, name, owner, info, supers, qname);
ClassSymbol classEnter(UnitInfo info,
Symbol owner,
int stubId,
int mods,
@ShortName int name,
@QNameId int[] superNames,
@QNameId int qname, int fileId) throws IOException {
int flags = checkFlags(mods, owner, info.getType() == IndexTree.BYTECODE);
@CompactArray(QualifiedName.class) Object supers = internSupers(mods, superNames);
ClassSymbol classSymbol = mySymbols.enterClass(fileId, stubId, flags, name, owner, info, supers, qname);
if (uncompleted != null) {
uncompleted.add(classSymbol);
}
if (tree.myDecls.length > 0) {
classSymbol.setMembers(enter(tree.myDecls, info, classSymbol, qname, fileId));
}
return classSymbol;
}
@Nullable
@CompactArray(QualifiedName.class)
private Object internSupers(int flags, int[][] superNames) {
Object internSupers(int flags, int[] superNames) {
if (BitUtil.isSet(flags, IndexTree.ANNOTATION)) {
return myNameEnvironment.annotation;
return myNameEnvironment.java_lang_annotation_Annotation;
}
boolean isEnum = BitUtil.isSet(flags, IndexTree.ENUM);
@@ -130,12 +72,12 @@ public class StubEnter {
return isEnum ? myNameEnvironment.java_lang_Enum : null;
}
if (superNames.length == 1 && !isEnum) {
return myNameEnvironment.concat(superNames[0], true);
return new QualifiedName(superNames[0]);
}
QualifiedName[] array = new QualifiedName[superNames.length + (isEnum ? 1 : 0)];
for (int i = 0; i < superNames.length; i++) {
array[i] = myNameEnvironment.concat(superNames[i], true);
array[i] = new QualifiedName(superNames[i]);
}
if (isEnum) {
array[array.length - 1] = myNameEnvironment.java_lang_Enum;
@@ -157,11 +99,18 @@ public class StubEnter {
uncompleted = null;
}
public static int checkFlags(long flags, Symbol owner) {
private static int checkFlags(long flags, Symbol owner, boolean compiled) {
int mask = 0;
if (owner.isClass() && (owner.myOwner.isPackage() || owner.isStatic())) {
if ((flags & (IndexTree.INTERFACE | IndexTree.ENUM | IndexTree.STATIC)) != 0 )
if ((flags & (IndexTree.INTERFACE | IndexTree.ENUM | IndexTree.STATIC)) != 0) {
mask |= IndexTree.STATIC;
}
}
if ((flags & IndexTree.SUPERS_UNRESOLVED) != 0) {
mask |= IndexTree.SUPERS_UNRESOLVED;
}
if (compiled) {
mask |= IndexTree.COMPILED;
}
return mask;
}
@@ -31,14 +31,14 @@ public class StubHierarchyConnector {
private void resolveName(Symbol.ClassSymbol place, QualifiedName name, Set<Symbol.ClassSymbol> result) throws IncompleteHierarchyException {
if (place.isCompiled()) {
Symbol.ClassSymbol[] candidates = myResolve.findGlobalType(name);
Symbol.ClassSymbol[] candidates = myResolve.findGlobalType(name.myId);
if (candidates.length == 0) {
throw new IncompleteHierarchyException();
}
Collections.addAll(result, candidates);
} else {
for (Symbol symbol : myResolve.resolveBase(place, name.myComponents)) {
for (Symbol symbol : myResolve.resolveBase(place, name.myId, false)) {
if (symbol instanceof Symbol.ClassSymbol) {
result.add((Symbol.ClassSymbol)symbol);
}
@@ -21,14 +21,17 @@ import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.psi.impl.java.stubs.index.JavaUnitDescriptor;
import com.intellij.psi.stubsHierarchy.StubHierarchyIndexer;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.DataInputOutputUtil;
import com.intellij.util.io.EnumeratorIntegerDescriptor;
import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.stream.IntStream;
@@ -36,29 +39,29 @@ import java.util.stream.IntStream;
/**
* @author peter
*/
public class StubHierarchyIndex extends FileBasedIndexExtension<Integer, IndexTree.Unit> implements PsiDependentIndex {
public class StubHierarchyIndex extends FileBasedIndexExtension<Integer, SerializedUnit> implements PsiDependentIndex {
private static final int KEY_COUNT = 20;
static final int[] BINARY_KEYS = IntStream.rangeClosed(1, KEY_COUNT).toArray();
static final int[] SOURCE_KEYS = IntStream.rangeClosed(-KEY_COUNT, -1).toArray();
static final ID<Integer, IndexTree.Unit> INDEX_ID = ID.create("jvm.hierarchy");
static final ID<Integer, SerializedUnit> INDEX_ID = ID.create("jvm.hierarchy");
private static final StubHierarchyIndexer[] ourIndexers = StubHierarchyIndexer.EP_NAME.getExtensions();
@NotNull
@Override
public ID<Integer, IndexTree.Unit> getName() {
public ID<Integer, SerializedUnit> getName() {
return INDEX_ID;
}
@NotNull
@Override
public DataIndexer<Integer, IndexTree.Unit, FileContent> getIndexer() {
public DataIndexer<Integer, SerializedUnit, FileContent> getIndexer() {
return inputData -> {
for (StubHierarchyIndexer indexer : ourIndexers) {
VirtualFile file = inputData.getFile();
IndexTree.Unit unit = indexer.handlesFile(file) ? indexer.indexFile(inputData) : null;
if (unit != null && unit.myDecls.length > 0) {
int[] keys = file.getFileType().isBinary() ? BINARY_KEYS : SOURCE_KEYS;
return Collections.singletonMap(keys[((VirtualFileWithId) file).getId() % keys.length], unit);
return Collections.singletonMap(keys[((VirtualFileWithId) file).getId() % keys.length], new SerializedUnit(unit));
}
}
return Collections.emptyMap();
@@ -73,13 +76,27 @@ public class StubHierarchyIndex extends FileBasedIndexExtension<Integer, IndexTr
@NotNull
@Override
public DataExternalizer<IndexTree.Unit> getValueExternalizer() {
return JavaUnitDescriptor.INSTANCE;
public DataExternalizer<SerializedUnit> getValueExternalizer() {
return new DataExternalizer<SerializedUnit>() {
@Override
public void save(@NotNull DataOutput out, SerializedUnit value) throws IOException {
byte[] bytes = value.getSerializedBytes();
DataInputOutputUtil.writeINT(out, bytes.length);
out.write(bytes);
}
@Override
public SerializedUnit read(@NotNull DataInput in) throws IOException {
byte[] bytes = new byte[DataInputOutputUtil.readINT(in)];
in.readFully(bytes);
return new SerializedUnit(bytes);
}
};
}
@Override
public int getVersion() {
return IndexTree.STUB_HIERARCHY_ENABLED ? 5 + Arrays.stream(ourIndexers).mapToInt(StubHierarchyIndexer::getVersion).sum() : 0;
return IndexTree.STUB_HIERARCHY_ENABLED ? 6 + Arrays.stream(ourIndexers).mapToInt(StubHierarchyIndexer::getVersion).sum() : 0;
}
@NotNull
@@ -17,6 +17,7 @@ package com.intellij.psi.stubsHierarchy.impl;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.util.BitUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,16 +37,22 @@ public class StubResolver {
}
// resolve class `sym` extends/implements `baseId`
Set<Symbol> resolveBase(Symbol.ClassSymbol sym, int[] baseId) throws IncompleteHierarchyException {
Set<Symbol> result = findIdent(sym.myOwner, sym.myUnitInfo, baseId[0], baseId.length > 1);
for (int i = 1; i < baseId.length; i++) {
Set<Symbol> prev = result;
int k = (i == baseId.length - 1) ? IndexTree.CLASS : IndexTree.CLASS | IndexTree.PACKAGE;
result = new HashSet<>();
for (Symbol symbol : prev) {
selectSym(symbol, baseId[i], k, result);
Set<Symbol> resolveBase(Symbol.ClassSymbol sym, @QNameId int name, boolean processPackages) throws IncompleteHierarchyException {
@QNameId int prefix = myNameEnvironment.prefixId(name);
@ShortName int shortName = myNameEnvironment.shortName(name);
if (prefix == NameEnvironment.NO_NAME) {
Set<Symbol> result = findIdent(sym.myOwner, sym.myUnitInfo, shortName, processPackages);
if (result.isEmpty()) {
throw IncompleteHierarchyException.INSTANCE;
}
return result;
}
int k = processPackages ? IndexTree.CLASS | IndexTree.PACKAGE : IndexTree.CLASS;
Set<Symbol> prev = resolveBase(sym, prefix, true);
Set<Symbol> result = new HashSet<>();
for (Symbol symbol : prev) {
selectSym(symbol, shortName, k, result);
}
if (result.isEmpty()) {
throw IncompleteHierarchyException.INSTANCE;
@@ -54,15 +61,15 @@ public class StubResolver {
}
@NotNull
private Set<Symbol> findIdent(Symbol startScope, UnitInfo info, int name, boolean processPackages) throws IncompleteHierarchyException {
private Set<Symbol> findIdent(Symbol startScope, UnitInfo info, @ShortName int name, boolean processPackages) throws IncompleteHierarchyException {
Set<Symbol> result = new HashSet<Symbol>();
findType(startScope, name, result);
findGlobalType(info, name, result);
if (processPackages) {
Symbol.PackageSymbol pkg = mySymbols.getPackage(myNameEnvironment.qualifiedName(null, name, false));
if (pkg != null)
result.add(pkg);
@QNameId int nameId = myNameEnvironment.findExistingName(0, name);
Symbol.PackageSymbol pkg = nameId < 0 ? null : mySymbols.getPackage(nameId);
ContainerUtil.addIfNotNull(result, pkg);
}
return result;
}
@@ -76,16 +83,16 @@ public class StubResolver {
}
// resolving `receiver.name`
private void selectSym(Symbol receiver, int name, int kind, Set<Symbol> symbols) throws IncompleteHierarchyException {
private void selectSym(Symbol receiver, @ShortName int name, int kind, Set<Symbol> symbols) throws IncompleteHierarchyException {
if (receiver.isPackage())
findIdentInPackage((Symbol.PackageSymbol)receiver, name, kind, symbols);
else
findMemberType(receiver, name, symbols);
}
private void findIdentInPackage(Symbol.PackageSymbol pck, int name, int kind, Set<Symbol> symbols) {
QualifiedName fullname = mySymbols.myNameEnvironment.qualifiedName(pck.myQualifiedName, name, false);
if (fullname == null) {
private void findIdentInPackage(Symbol.PackageSymbol pck, @ShortName int name, int kind, Set<Symbol> symbols) {
@QNameId int fullname = mySymbols.myNameEnvironment.findExistingName(pck.myQualifiedName, name);
if (fullname < 0) {
return;
}
if (BitUtil.isSet(kind, IndexTree.PACKAGE)) {
@@ -94,11 +101,11 @@ public class StubResolver {
symbols.add(pkg);
}
if (BitUtil.isSet(kind, IndexTree.CLASS)) {
Collections.addAll(symbols, loadClass(fullname));
Collections.addAll(symbols, findGlobalType(fullname));
}
}
private void findMemberType(Symbol s, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
private void findMemberType(Symbol s, @ShortName int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
if (s.isClass()) {
processInheritedMembers((Symbol.ClassSymbol)s, name, false, symbols, null);
} else {
@@ -107,7 +114,7 @@ public class StubResolver {
}
private void processInheritedMembers(Symbol.ClassSymbol s,
int name,
@ShortName int name,
boolean requireStatic,
Set<Symbol> symbols,
@Nullable Set<Symbol> processed) throws IncompleteHierarchyException {
@@ -128,23 +135,19 @@ public class StubResolver {
}
}
private Symbol.ClassSymbol[] loadClass(@NotNull QualifiedName fqn) {
return mySymbols.loadClass(fqn);
public Symbol.ClassSymbol[] findGlobalType(@QNameId int nameId) {
return mySymbols.loadClass(nameId);
}
public Symbol.ClassSymbol[] findGlobalType(@NotNull QualifiedName name) {
return loadClass(name);
}
private void findGlobalType(UnitInfo info, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
private void findGlobalType(UnitInfo info, @ShortName int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
for (long anImport : Translator.getDefaultImports(info.getType(), myNameEnvironment))
handleImport(anImport, name, symbols);
for (long anImport : info.getImports())
handleImport(anImport, name, symbols);
}
public void handleImport(long tree, int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
QualifiedName fullname = Imports.getFullName(tree, myNameEnvironment);
public void handleImport(long tree, @ShortName int name, Set<Symbol> symbols) throws IncompleteHierarchyException {
@QNameId int fullname = Imports.getFullNameId(tree);
if (Imports.isOnDemand(tree)) {
if (Imports.isStatic(tree)) {
for (Symbol.ClassSymbol p : findGlobalType(fullname))
@@ -155,12 +158,12 @@ public class StubResolver {
}
}
else {
QualifiedName prefix = myNameEnvironment.prefix(fullname);
if (prefix.isEmpty()) {
@QNameId int prefix = myNameEnvironment.prefixId(fullname);
if (prefix == 0) {
return;
}
int shortName = myNameEnvironment.shortName(fullname);
int alias = Imports.getAlias(tree);
@ShortName int shortName = myNameEnvironment.shortName(fullname);
@ShortName int alias = Imports.getAlias(tree);
boolean shouldImport = ((alias & name) == name) || shortName == name;
if (!shouldImport)
return;
@@ -175,22 +178,19 @@ public class StubResolver {
}
// handling of `import prefix.*`
private void importAll(@NotNull final QualifiedName prefix, int suffix, final Set<Symbol> symbols) {
QualifiedName fullname = myNameEnvironment.qualifiedName(prefix, suffix, false);
// existing only
if (fullname != null) {
Symbol.ClassSymbol[] ss = findGlobalType(fullname);
Collections.addAll(symbols, ss);
}
private void importAll(@QNameId int prefix, @ShortName int suffix, final Set<Symbol> symbols) {
@QNameId int fullname = myNameEnvironment.findExistingName(prefix, suffix);
if (fullname >= 0) {
Collections.addAll(symbols, findGlobalType(fullname));
}
}
// handling of import static `tsym.name` as
private void importNamedStatic(final Symbol.ClassSymbol tsym, final int name, final Set<Symbol> symbols) throws IncompleteHierarchyException {
private void importNamedStatic(final Symbol.ClassSymbol tsym, @ShortName final int name, final Set<Symbol> symbols) throws IncompleteHierarchyException {
processInheritedMembers(tsym, name, true, symbols, null);
}
private static void processMembers(Symbol.ClassSymbol[] members, int name, Set<Symbol> symbols, boolean requireStatic) {
private static void processMembers(Symbol.ClassSymbol[] members, @ShortName int name, Set<Symbol> symbols, boolean requireStatic) {
int index = getIndex(name, members);
if (index < 0) return;
@@ -21,9 +21,7 @@ import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
import java.util.*;
/**
* Java symbols needed for hierarchy building. Mostly classes ({@link ClassSymbol}) or packages ({@link PackageSymbol}),
@@ -74,9 +72,9 @@ public abstract class Symbol {
}
public static class PackageSymbol extends Symbol {
final QualifiedName myQualifiedName;
@QNameId final int myQualifiedName;
public PackageSymbol(Symbol owner, QualifiedName fullname, int name) {
public PackageSymbol(Symbol owner, @QNameId int fullname, int name) {
super(IndexTree.PACKAGE, owner, name);
myQualifiedName = fullname;
}
@@ -85,7 +83,6 @@ public abstract class Symbol {
/** A class for class symbols
*/
public static class ClassSymbol extends MemberSymbol {
private static final int HIERARCHY_INCOMPLETE = 1 << 20;
private static final int CONNECT_STARTED = 1 << 21;
public static final ClassSymbol[] EMPTY_ARRAY = new ClassSymbol[0];
@@ -101,8 +98,10 @@ public abstract class Symbol {
@CompactArray(QualifiedName.class) Object supers) {
super(flags | IndexTree.CLASS, owner, name);
this.myAnchorId = anchorId;
this.mySuperClasses = supers;
this.myUnitInfo = unitInfo;
boolean incomplete = isHierarchyIncomplete();
this.mySuperClasses = incomplete ? null : supers;
this.myUnitInfo = incomplete ? null : unitInfo;
}
@Override
@@ -150,7 +149,7 @@ public abstract class Symbol {
void markHierarchyIncomplete() {
setSupers(Collections.emptySet());
myFlags = BitUtil.set(myFlags, HIERARCHY_INCOMPLETE, true);
myFlags = BitUtil.set(myFlags, IndexTree.SUPERS_UNRESOLVED, true);
}
void setSupers(Set<ClassSymbol> supers) {
@@ -161,7 +160,7 @@ public abstract class Symbol {
}
boolean isHierarchyIncomplete() {
return BitUtil.isSet(myFlags, HIERARCHY_INCOMPLETE);
return BitUtil.isSet(myFlags, IndexTree.SUPERS_UNRESOLVED);
}
boolean hasAmbiguousSupers() {
@@ -186,7 +185,7 @@ public abstract class Symbol {
@CompactArray(ClassSymbol.class) private Object myMembers = null;
MemberSymbol(Symbol owner) {
super(IndexTree.MEMBER, owner, NamesEnumerator.NO_NAME);
super(IndexTree.MEMBER, owner, NameEnvironment.NO_NAME);
}
MemberSymbol(int flags, Symbol owner, int name) {
@@ -199,12 +198,18 @@ public abstract class Symbol {
(ClassSymbol[])myMembers;
}
void setMembers(ClassSymbol[] members) {
myMembers = members.length == 0 ? null : members.length == 1 ? members[0] : members;
void setMembers(List<ClassSymbol> members) {
myMembers = members.isEmpty() ? null : members.size() == 1 ? members.get(0) : toSortedArray(members);
}
private static ClassSymbol[] toSortedArray(List<ClassSymbol> members) {
ClassSymbol[] array = members.toArray(new ClassSymbol[members.size()]);
Arrays.sort(array, CLASS_SYMBOL_BY_NAME_COMPARATOR);
return array;
}
}
public static final Comparator<ClassSymbol> CLASS_SYMBOL_BY_NAME_COMPARATOR = (s1, s2) -> {
private static final Comparator<ClassSymbol> CLASS_SYMBOL_BY_NAME_COMPARATOR = (s1, s2) -> {
int name1 = s1.myShortName;
int name2 = s2.myShortName;
return (name1 < name2) ? -1 : ((name1 == name2) ? 0 : 1);
@@ -21,35 +21,29 @@ public class Symbols {
private Object[] myClassSymbolsByNameId = new Object[0x8000];
protected Symbols() {
myRootPackage = new PackageSymbol(null, myNameEnvironment.empty, NamesEnumerator.NO_NAME);
myPackages.put(myNameEnvironment.empty.myId, myRootPackage);
myRootPackage = new PackageSymbol(null, 0, NameEnvironment.NO_NAME);
myPackages.put(0, myRootPackage);
}
public PackageSymbol enterPackage(QualifiedName qualifiedName) {
PackageSymbol p = myPackages.get(qualifiedName.myId);
public PackageSymbol enterPackage(@QNameId int qualifiedName) {
PackageSymbol p = myPackages.get(qualifiedName);
if (p == null) {
PackageSymbol owner = enterPackage(myNameEnvironment.prefix(qualifiedName));
PackageSymbol owner = enterPackage(myNameEnvironment.prefixId(qualifiedName));
int shortName = myNameEnvironment.shortName(qualifiedName);
p = new PackageSymbol(owner, qualifiedName, shortName);
myPackages.put(qualifiedName.myId, p);
myPackages.put(qualifiedName, p);
}
return p;
}
@Nullable
public PackageSymbol getPackage(QualifiedName qualifiedName) {
if (qualifiedName == null)
return null;
return myPackages.get(qualifiedName.myId);
PackageSymbol getPackage(@QNameId int qualifiedName) {
return myPackages.get(qualifiedName);
}
@NotNull
public ClassSymbol[] loadClass(@NotNull QualifiedName qualifiedName) {
int i = qualifiedName.myId;
if (i >= myClassSymbolsByNameId.length) {
return ClassSymbol.EMPTY_ARRAY;
}
return getClassSymbols(i);
ClassSymbol[] loadClass(@QNameId int name) {
return name >= myClassSymbolsByNameId.length ? ClassSymbol.EMPTY_ARRAY : getClassSymbols(name);
}
private ClassSymbol[] getClassSymbols(int id) {
@@ -70,12 +64,12 @@ public class Symbols {
Symbol owner,
UnitInfo info,
@CompactArray(QualifiedName.class) Object supers,
@Nullable QualifiedName qualifiedName) {
@QNameId int qualifiedName) {
int anchorId = myClassAnchors.registerClass(fileId, stubId);
ClassSymbol c = new ClassSymbol(anchorId, flags, owner, shortName, info, supers);
myClassSymbols.add(c);
if (qualifiedName != null) {
putClassByName(c, qualifiedName.myId);
if (qualifiedName >= 0) {
putClassByName(c, qualifiedName);
}
return c;
}
@@ -33,7 +33,7 @@ public class Translator {
private static long[] createDefaultJavaImports(NameEnvironment nameEnvironment) {
return new long[]{
Imports.mkImport(nameEnvironment.fromString("java.lang", true), false, true, 0)
Imports.mkImport(nameEnvironment.fromString("java.lang"), false, true, 0)
};
}
@@ -48,14 +48,14 @@ public class Translator {
private static long[] createDefaultGroovyImports(NameEnvironment nameEnvironment) {
return new long[] {
Imports.mkImport(nameEnvironment.fromString("java.lang", true), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.util", true), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.io", true), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.net", true), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("groovy.lang", true), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("groovy.util", true), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.math.BigInteger", true), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.math.BigDecimal", true), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.lang"), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.util"), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.io"), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.net"), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("groovy.lang"), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("groovy.util"), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.math.BigInteger"), false, true, 0),
Imports.mkImport(nameEnvironment.fromString("java.math.BigDecimal"), false, true, 0),
};
}
@@ -15,8 +15,12 @@
*/
package com.intellij.psi.stubsHierarchy.impl;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* This annotation exists for documentation purposes only.<p/>
@@ -24,10 +28,23 @@ import java.lang.annotation.RetentionPolicy;
* The value annotated with this annotation is used to save memory when storing mostly-singular or empty collections.
* For empty collection, 'null' value is used. For one-element collection, the value is the single element. Otherwise,
* an array is used. Possible component types are specified in the annotation value.
*
* @author peter
*/
@Retention(RetentionPolicy.SOURCE)
public @interface CompactArray {
@Target(ElementType.TYPE_USE)
@interface CompactArray {
Class[] value();
}
/**
* int id of a qualified name in a {@link NameEnvironment}
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE_USE)
@interface QNameId { }
/**
* int hash of a qualified name part, produced by {@link IndexTree#hashIdentifier(String)}
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE_USE)
@interface ShortName { }
@@ -23,13 +23,22 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiTypeParameter;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.impl.source.PsiFileWithStubSupport;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubTree;
import com.intellij.psi.stubsHierarchy.ClassHierarchy;
import com.intellij.psi.stubsHierarchy.HierarchyService;
import com.intellij.psi.stubsHierarchy.SmartClassAnchor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -72,14 +81,48 @@ public class TestStubHierarchyAction extends InheritanceAction {
}
private void compareSupers(ProgressIndicator indicator, MultiMap<SmartClassAnchor, SmartClassAnchor> supers, ClassHierarchy hierarchy) {
List<? extends SmartClassAnchor> anchors = hierarchy.getCoveredClasses();
for (int i = 0; i < anchors.size(); i++) {
indicator.setFraction(i * 1.0 / anchors.size());
SmartClassAnchor anchor = anchors.get(i);
compareSupers(anchor, supers.get(anchor));
List<VirtualFile> covered = getCoveredFiles(indicator, hierarchy);
for (int i = 0; i < covered.size(); i++) {
indicator.setFraction(i * 1.0 / covered.size());
checkFile(supers, hierarchy, covered.get(i));
}
}
private void checkFile(MultiMap<SmartClassAnchor, SmartClassAnchor> supers, ClassHierarchy hierarchy, VirtualFile vFile) {
for (StubElement<?> element : getStubTree(vFile).getPlainListFromAllRoots()) {
Object psi = element.getPsi();
if (psi instanceof PsiClass && !(psi instanceof PsiTypeParameter)) {
SmartClassAnchor anchor = hierarchy.findAnchor((PsiClass)psi);
if (anchor == null) {
throw new AssertionError("Class not indexed: " + psi + " in " + vFile);
}
compareSupers(anchor, supers.get(anchor));
}
}
}
@NotNull
private List<VirtualFile> getCoveredFiles(ProgressIndicator indicator, ClassHierarchy hierarchy) {
GlobalSearchScope allScope = GlobalSearchScope.allScope(myProject);
GlobalSearchScope uncovered = hierarchy.restrictToUncovered(allScope);
List<VirtualFile> covered = new ArrayList<>();
FileBasedIndex.getInstance().iterateIndexableFiles(file -> {
if (!file.isDirectory() && allScope.contains(file) && !uncovered.contains(file)) {
covered.add(file);
}
return true;
}, myProject, indicator);
return covered;
}
@NotNull
private StubTree getStubTree(VirtualFile vFile) {
PsiFileWithStubSupport psiFile = (PsiFileWithStubSupport)PsiManager.getInstance(myProject).findFile(vFile);
assert psiFile != null : "No PSI for " + vFile;
StubTree stubTree = psiFile.getStubTree();
return stubTree != null ? stubTree : ((PsiFileImpl)psiFile).calcStubTree();
}
private void compareSupers(final SmartClassAnchor anchor, final Collection<SmartClassAnchor> superAnchors) {
PsiClass subClass = anchor.retrieveClass(myProject);
List<PsiClass> stubSuperList = ContainerUtil.map(superAnchors, (anchor1) -> anchor1.retrieveClass(myProject));
@@ -41,7 +41,7 @@ public class JavaShortClassNameIndex extends StringStubIndexExtension<PsiClass>
@Override
public int getVersion() {
return super.getVersion() + (FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping ? 1 : 0);
return super.getVersion() + (FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping ? 2 : 0);
}
@NotNull
@@ -1,168 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.java.stubs.index;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.util.BitUtil;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.DataInputOutputUtil;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static com.intellij.psi.impl.java.stubs.index.JavaUnitDescriptor.ImportFlags.*;
public class JavaUnitDescriptor implements DataExternalizer<IndexTree.Unit> {
public static final JavaUnitDescriptor INSTANCE = new JavaUnitDescriptor();
private static void writeIntArray(DataOutput out, int[] array) throws IOException {
DataInputOutputUtil.writeINT(out, array.length);
for (int i : array) {
out.writeInt(i);
}
}
private static int[] readIntArray(DataInput in) throws IOException {
int length = DataInputOutputUtil.readINT(in);
int[] result = new int[length];
for (int i = 0; i < length; i++) {
result[i] = in.readInt();
}
return result;
}
@Override
public void save(@NotNull DataOutput out, IndexTree.Unit value) throws IOException {
writeIntArray(out, value.myPackageName);
out.writeByte(value.myUnitType);
if (value.myUnitType != IndexTree.BYTECODE) {
DataInputOutputUtil.writeINT(out, value.imports.length);
for (IndexTree.Import anImport : value.imports) {
writeImport(out, anImport);
}
}
// class Declaration
DataInputOutputUtil.writeINT(out, value.myDecls.length);
for (IndexTree.ClassDecl def : value.myDecls) {
saveClassDecl(out, def);
}
}
private void saveClassDecl(@NotNull DataOutput out, IndexTree.ClassDecl value) throws IOException {
DataInputOutputUtil.writeINT(out, value.myStubId);
DataInputOutputUtil.writeINT(out, value.myMods);
out.writeInt(value.myName);
DataInputOutputUtil.writeINT(out, value.mySupers.length);
for (int[] aSuper : value.mySupers) {
writeIntArray(out, aSuper);
}
DataInputOutputUtil.writeINT(out, value.myDecls.length);
for (IndexTree.Decl def : value.myDecls) {
saveDecl(out, def);
}
}
private void saveDecl(@NotNull DataOutput out, IndexTree.Decl value) throws IOException {
if (value instanceof IndexTree.ClassDecl) {
out.writeBoolean(true);
saveClassDecl(out, (IndexTree.ClassDecl)value);
} else if (value instanceof IndexTree.MemberDecl) {
out.writeBoolean(false);
IndexTree.MemberDecl memberDecl = (IndexTree.MemberDecl)value;
DataInputOutputUtil.writeINT(out, memberDecl.myDecls.length);
for (IndexTree.Decl def : memberDecl.myDecls) {
saveDecl(out, def);
}
}
}
@Override
public IndexTree.Unit read(@NotNull DataInput in) throws IOException {
int[] pid = readIntArray(in);
byte type = in.readByte();
IndexTree.Import[] imports = IndexTree.Import.EMPTY_ARRAY;
if (type != IndexTree.BYTECODE) {
imports = new IndexTree.Import[DataInputOutputUtil.readINT(in)];
for (int i = 0; i < imports.length; i++) {
imports[i] = readImport(in);
}
}
IndexTree.ClassDecl[] classes = new IndexTree.ClassDecl[DataInputOutputUtil.readINT(in)];
for (int i = 0; i < classes.length; i++) {
classes[i] = readClassDecl(in);
}
return new IndexTree.Unit(pid, type, imports, classes);
}
private IndexTree.ClassDecl readClassDecl(DataInput in) throws IOException {
int stubId = DataInputOutputUtil.readINT(in);
int mods = DataInputOutputUtil.readINT(in);
int name = in.readInt();
int[][] supers = new int[DataInputOutputUtil.readINT(in)][];
for (int i = 0; i < supers.length; i++) {
supers[i] = readIntArray(in);
}
IndexTree.Decl[] decls = new IndexTree.Decl[DataInputOutputUtil.readINT(in)];
for (int i = 0; i < decls.length; i++) {
decls[i] = readDecl(in);
}
return new IndexTree.ClassDecl(stubId, mods, name, supers, decls);
}
private IndexTree.Decl readDecl(DataInput in) throws IOException {
boolean isClassDecl = in.readBoolean();
if (isClassDecl) {
return readClassDecl(in);
}
else {
IndexTree.Decl[] decls = new IndexTree.Decl[DataInputOutputUtil.readINT(in)];
for (int i = 0; i < decls.length; i++) {
decls[i] = readDecl(in);
}
return new IndexTree.MemberDecl(decls);
}
}
interface ImportFlags {
int IS_STATIC = 1;
int IS_ON_DEMAND = 2;
int HAS_ALIAS = 4;
}
private static void writeImport(@NotNull DataOutput out, IndexTree.Import anImport) throws IOException {
writeIntArray(out, anImport.myFullname);
boolean hasAlias = anImport.myAlias != 0;
int flags = 0;
flags = BitUtil.set(flags, IS_STATIC, anImport.myStaticImport);
flags = BitUtil.set(flags, IS_ON_DEMAND, anImport.myOnDemand);
flags = BitUtil.set(flags, HAS_ALIAS, hasAlias);
out.writeByte(flags);
if (hasAlias) {
out.writeInt(anImport.myAlias);
}
}
@NotNull
private static IndexTree.Import readImport(@NotNull DataInput in) throws IOException {
int[] fullname = readIntArray(in);
int flags = in.readByte();
return new IndexTree.Import(fullname,
BitUtil.isSet(flags, IS_STATIC), BitUtil.isSet(flags, IS_ON_DEMAND),
BitUtil.isSet(flags, HAS_ALIAS) ? in.readInt() : 0);
}
}
@@ -18,6 +18,7 @@ package com.intellij.psi.stubsHierarchy;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -43,6 +44,9 @@ public abstract class ClassHierarchy {
@NotNull
public abstract SmartClassAnchor[] getDirectSubtypeCandidates(@NotNull SmartClassAnchor anchor);
@Nullable
public abstract SmartClassAnchor findAnchor(@NotNull PsiClass psiClass);
/**
* @return whether stub hierarchy resolver couldn't determine the super class exactly because there were several possible candidates
*/
@@ -117,22 +117,14 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
if (glb instanceof PsiWildcardType) {
return glb;
}
if (glb != null ) {
return glb instanceof PsiCapturedWildcardType ? ((PsiCapturedWildcardType)glb).getWildcard()
: PsiWildcardType.createExtends(typeParameter.getManager(), glb);
if (glb instanceof PsiCapturedWildcardType) {
PsiWildcardType wildcard = ((PsiCapturedWildcardType)glb).getWildcard();
if (!wildcard.isSuper()) return wildcard;
}
/*
if (glb instanceof PsiCapturedWildcardType) {
PsiWildcardType wildcard = ((PsiCapturedWildcardType)glb).getWildcard();
if (!wildcard.isSuper()) return wildcard;
}
if (glb != null ) {
return PsiWildcardType.createExtends(typeParameter.getManager(), glb);
}
*/
if (glb != null) {
return PsiWildcardType.createExtends(typeParameter.getManager(), glb);
}
}
return substituted;
}
@@ -38,6 +38,7 @@ public class IndexTree {
public static final int ENUM = 1 << 6;
public static final int COMPILED = 1 << 7;
public static final int MEMBER = 1 << 8;
public static final int SUPERS_UNRESOLVED = 1 << 9;
public static final byte BYTECODE = 0;
public static final byte JAVA = 1;
@@ -0,0 +1,13 @@
import a.Provider;
public abstract class Test<T> {
private void configure(Provider<T> provider,
Test<? super T> sBind,
Test<? extends T> eBind) {
sBind.toProvider(provider);
eBind.toProvider<error descr="Cannot resolve method 'toProvider(a.Provider<T>)'">(provider)</error><EOLError descr="';' expected"></EOLError>
}
abstract void toProvider(Provider<? extends T> var1);
abstract void toProvider(b.Provider<? extends T> var1);
}
@@ -6,6 +6,7 @@ public class CodeBlockBody {
for (Iterator<Integer> it2 = it1; it2.hasNext(); ) {
Integer integer = it2.next();
System.out.println(integer + " a");
// a comment
System.out.println(integer + " b");
}
}
@@ -0,0 +1,10 @@
// "Replace 'for each' loop with iterator 'for' loop" "true"
import java.util.Iterator;
public class EmptyBlockBody {
void foo(Iterator<Integer> it) {
for (Iterator<Integer> it1 = it; it1.hasNext(); ) {
Integer integer = it1.next();
}
}
}
@@ -5,6 +5,7 @@ public class CodeBlockBody {
void foo(Iterator<Integer> it,Iterator<Integer> it1) {
for (Integer integer : <caret>it1) {
System.out.println(integer + " a");
// a comment
System.out.println(integer + " b");
}
}
@@ -0,0 +1,8 @@
// "Replace 'for each' loop with iterator 'for' loop" "true"
import java.util.Iterator;
public class EmptyBlockBody {
void foo(Iterator<Integer> it) {
for (Integer integer : <caret>it) {}
}
}
@@ -47,6 +47,14 @@ public class LightAdvHighlightingFixtureTest extends LightCodeInsightFixtureTest
assertNull(ReferencesSearch.search(aClass).findFirst());
}
public void testBoundsPromotionWithCapturedWildcards() throws Exception {
myFixture.addClass("package a; public interface Provider<A> {}");
myFixture.addClass("package b; public interface Provider<B> {}");
myFixture.configureByFile(getTestName(false) + ".java");
myFixture.checkHighlighting();
}
@Override
protected String getBasePath() {
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/daemonCodeAnalyzer/advFixture";
@@ -28,9 +28,9 @@ public class ReplaceIteratorForEachLoopWithIteratorForLoopFixTest extends LightQ
public void test() throws Exception { doAllTests(); }
@Override
protected void beforeActionStarted(String testName, String contents) {
super.beforeActionStarted(testName, contents);
if (testName.startsWith("Final")) {
protected void setUp() throws Exception {
super.setUp();
if (getTestName(false).startsWith("Final")) {
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject());
myFinalLocals = codeStyleSettings.GENERATE_FINAL_LOCALS;
codeStyleSettings.GENERATE_FINAL_LOCALS = true;
@@ -38,12 +38,16 @@ public class ReplaceIteratorForEachLoopWithIteratorForLoopFixTest extends LightQ
}
@Override
protected void afterActionCompleted(String testName, String contents) {
if (testName.startsWith("Final")) {
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject());
codeStyleSettings.GENERATE_FINAL_LOCALS = myFinalLocals;
protected void tearDown() throws Exception {
try {
if (getTestName(false).startsWith("Final")) {
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject());
codeStyleSettings.GENERATE_FINAL_LOCALS = myFinalLocals;
}
}
finally {
super.tearDown();
}
super.afterActionCompleted(testName, contents);
}
@Override
@@ -51,6 +51,7 @@ import com.intellij.testFramework.exceptionCases.IllegalArgumentExceptionCase
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
import com.intellij.util.Processor
import com.intellij.util.indexing.FileBasedIndex
import com.intellij.util.indexing.FileBasedIndexImpl
import com.intellij.util.indexing.MapIndexStorage
import com.intellij.util.indexing.StorageException
import com.intellij.util.io.*
@@ -409,6 +410,27 @@ public class IndexTest extends JavaCodeInsightFixtureTestCase {
}
}
public void "test no index stamp update when no change"() throws IOException {
final VirtualFile vFile = myFixture.addClass("class Foo {}").getContainingFile().getVirtualFile();
def stamp = ((FileBasedIndexImpl)FileBasedIndex.instance).getIndexModificationStamp(IdIndex.NAME, project)
VfsUtil.saveText(vFile, "Foo class")
assertTrue(stamp == ((FileBasedIndexImpl)FileBasedIndex.instance).getIndexModificationStamp(IdIndex.NAME, project))
VfsUtil.saveText(vFile, "class Foo2 {}")
assertTrue(stamp != ((FileBasedIndexImpl)FileBasedIndex.instance).getIndexModificationStamp(IdIndex.NAME, project))
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
document.setText("Foo2 class")
stamp = ((FileBasedIndexImpl)FileBasedIndex.instance).getIndexModificationStamp(IdIndex.NAME, project)
document.setText("class Foo2")
assertTrue(stamp == ((FileBasedIndexImpl)FileBasedIndex.instance).getIndexModificationStamp(IdIndex.NAME, project))
document.setText("Foo3 class");
PsiDocumentManager.getInstance(project).commitAllDocuments();
assertTrue(stamp != ((FileBasedIndexImpl)FileBasedIndex.instance).getIndexModificationStamp(IdIndex.NAME, project))
}
public void "test do not collect stub tree while holding stub elements"() throws IOException {
final VirtualFile vFile = myFixture.addClass("class Foo {}").getContainingFile().getVirtualFile();
@@ -37,11 +37,11 @@ class RecentTestsOrderTest: LightIdeaTestCase() {
}
fun addPassedSuite(suiteUrl: String, date: Date = Date(), runConfiguration: RunnerAndConfigurationSettings = allTests) {
data.addSuite(suiteUrl, PASSED_INDEX, date, runConfiguration)
data.addSuite(suiteUrl, date, runConfiguration)
}
fun addFailedSuite(suiteUrl: String, date: Date = Date(), runConfiguration: RunnerAndConfigurationSettings = allTests) {
data.addSuite(suiteUrl, FAILED_INDEX, date, runConfiguration)
data.addSuite(suiteUrl, date, runConfiguration)
}
fun addPassedTest(testUrl: String, date: Date = Date(), runConfiguration: RunnerAndConfigurationSettings = allTests) {
@@ -57,11 +57,11 @@ class RecentTestsOrderTest: LightIdeaTestCase() {
val test1 = "MySingleTest.test1".test()
data.addTest(test1, PASSED_INDEX, now, allTests)
data.addSuite(suite, PASSED_INDEX, now, allTests)
data.addSuite(suite, now, allTests)
val testsToShow = data.getTestsToShow()
assertThat(testsToShow).hasSize(1)
assertThat(testsToShow[0].presentation).isEqualTo("MySingleTest")
assertThat(testsToShow[0].presentation).isEqualTo("all tests")
}
fun `test run configuration with multiple suites shows run configuration name`() {
@@ -90,13 +90,10 @@ class RecentTestsOrderTest: LightIdeaTestCase() {
addFailedTest(test)
val tests = data.getTestsToShow()
assertThat(tests).hasSize(2)
assertThat(tests).hasSize(1)
assertThat(tests[0].presentation).isEqualTo("SingleTest.test")
assertThat(tests[0].magnitude).isEqualTo(FAILED_INDEX)
assertThat(tests[1].presentation).isEqualTo("SingleTest")
assertThat(tests[1].magnitude).isEqualTo(FAILED_INDEX)
assertThat(tests[0].failed).isEqualTo(true)
}
fun `test show failed suite and test in run configuration`() {
@@ -111,41 +108,29 @@ class RecentTestsOrderTest: LightIdeaTestCase() {
addPassedSuite("PassedSuite".suite())
val tests = data.getTestsToShow()
assertThat(tests).hasSize(3)
assertThat(tests).hasSize(1)
assertThat(tests[0].presentation).isEqualTo("SingleTest.test")
assertThat(tests[0].magnitude).isEqualTo(FAILED_INDEX)
assertThat(tests[1].presentation).isEqualTo("SingleTest")
assertThat(tests[1].magnitude).isEqualTo(FAILED_INDEX)
assertThat(tests[2].presentation).isEqualTo("all tests")
assertThat(tests[2].magnitude).isEqualTo(FAILED_INDEX)
assertThat(tests[0].failed).isEqualTo(true)
}
fun `test single test run doesn't override suite status`() {
val singleTestConfig = mockConfiguration("single test", "Junit.single test")
val newNow = Date(now.time + 100000)
//current single test run
addFailedSuite("Test".suite(), newNow, singleTestConfig)
addFailedTest("Test.testOK".test(), newNow, singleTestConfig)
//previous all suite run
addPassedTest("Test.testOK".test(), now, allTests)
addFailedTest("Test.testFailed".test(), now, allTests)
//current single test run
addPassedSuite("Test".suite(), newNow, singleTestConfig)
addPassedTest("Test.testOK".test(), newNow, singleTestConfig)
val tests = data.getTestsToShow()
assertThat(tests).hasSize(3)
assertThat(tests[0].presentation).isEqualTo("Test.testOK")
assertThat(tests[0].magnitude).isEqualTo(FAILED_INDEX)
assertThat(tests).hasSize(2)
assertThat(tests[0].presentation).isEqualTo("single test")
assertThat(tests[1].presentation).isEqualTo("Test.testFailed")
assertThat(tests[1].magnitude).isEqualTo(FAILED_INDEX)
assertThat(tests[2].presentation).isEqualTo("Test")
assertThat(tests[2].magnitude).isEqualTo(FAILED_INDEX)
}
@@ -156,18 +141,15 @@ class RecentTestsOrderTest: LightIdeaTestCase() {
//previous all suite run
addPassedTest("Test.testOK".test(), now, allTests)
addFailedTest("Test.testFailed".test(), now, allTests)
//current single test run
addFailedSuite("Test".suite(), newNow, singleTestConfig)
addFailedTest("Test.testOK".test(), newNow, singleTestConfig)
addFailedTest("Test.testFailed".test(), newNow, singleTestConfig)
val tests = data.getTestsToShow()
assertThat(tests).hasSize(3)
assertThat(tests).hasSize(1)
assertThat(tests[0].presentation).isEqualTo("Test.testOK")
assertThat(tests[1].presentation).isEqualTo("Test.testFailed")
assertThat(tests[2].presentation).isEqualTo("Test")
assertThat(tests[0].presentation).isEqualTo("Test.testFailed")
}
}
@@ -48,18 +48,10 @@ class RecentTestsStepTest: LightIdeaTestCase() {
now = Date()
}
fun `test show suites without run configuration`() {
data.addTest("Test.x".test(), PASSED_INDEX, now, null)
data.addSuite("Test".suite(), PASSED_INDEX, now, null)
val tests = data.getTestsToShow()
assertThat(tests).hasSize(1)
}
fun `test all tests passed`() {
data.addTest("Test.textXXX".test(), PASSED_INDEX, now, allTests)
data.addSuite("Test".suite(), PASSED_INDEX, now, allTests)
data.addSuite("JFSDTest".suite(), PASSED_INDEX, now, allTests)
data.addSuite("Test".suite(), now, allTests)
data.addSuite("JFSDTest".suite(), now, allTests)
data.addTest("Test.textYYY".test(), PASSED_INDEX, now, allTests)
data.addTest("JFSDTest.testItMakesMeSadToFixIt".test(), PASSED_INDEX, now, allTests)
data.addTest("Test.textZZZ".test(), PASSED_INDEX, now, allTests)
@@ -73,8 +65,8 @@ class RecentTestsStepTest: LightIdeaTestCase() {
fun `test if one failed in run configuration show failed suite`() {
data.addSuite("JFSDTest".suite(), FAILED_INDEX, now, allTests)
data.addSuite("Test".test(), PASSED_INDEX, now, allTests)
data.addSuite("JFSDTest".suite(), now, allTests)
data.addSuite("Test".suite(), now, allTests)
data.addTest("JFSDTest.testItMakesMeSadToFixIt".test(), FAILED_INDEX, now, allTests)
data.addTest("JFSDTest.testUnconditionalAlignmentErrorneous".test(), PASSED_INDEX, now, allTests)
@@ -83,28 +75,21 @@ class RecentTestsStepTest: LightIdeaTestCase() {
val tests = data.getTestsToShow()
assertThat(tests).hasSize(3)
assertThat(tests).hasSize(1)
assertThat(tests[0].presentation).isEqualTo("JFSDTest.testItMakesMeSadToFixIt")
assertThat(tests[0].magnitude).isEqualTo(FAILED_INDEX)
assertThat(tests[1].presentation).isEqualTo("JFSDTest")
assertThat(tests[1].magnitude).isEqualTo(FAILED_INDEX)
assertThat(tests[2].presentation).isEqualTo("all tests")
assertThat(tests[2].magnitude).isEqualTo(FAILED_INDEX)
assertThat(tests[0].failed).isEqualTo(true)
}
fun `test if configuration with single test show failed test`() {
data.addSuite("JFSDTest".suite(), FAILED_INDEX, now, allTests)
data.addSuite("JFSDTest".suite(), now, allTests)
data.addTest("JFSDTest.testItMakesMeSadToFixIt".test(), FAILED_INDEX, now, allTests)
data.addTest("JFSDTest.testUnconditionalAlignmentErrorneous".test(), PASSED_INDEX, now, allTests)
val tests = data.getTestsToShow()
assertThat(tests).hasSize(2)
assertThat(tests).hasSize(1)
assertThat(tests[0].presentation).isEqualTo("JFSDTest.testItMakesMeSadToFixIt")
assertThat(tests[1].presentation).isEqualTo("JFSDTest")
}
@@ -326,7 +326,7 @@ public class ExternalJavacManager {
private class CompilationRequestsHandler extends SimpleChannelInboundHandler<JavacRemoteProto.Message> {
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
JavacProcessDescriptor descriptor = ctx.channel().attr(SESSION_DESCRIPTOR).get();
JavacProcessDescriptor descriptor = ctx.channel().attr(SESSION_DESCRIPTOR).getAndRemove();
if (descriptor != null) {
descriptor.setDone();
}
@@ -15,7 +15,6 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.NullableLazyValue;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VfsUtil;
@@ -99,7 +98,10 @@ public class JsonSchemaServiceImpl implements JsonSchemaServiceEx {
for (JsonSchemaProviderFactory factory : factories) {
final List<JsonSchemaFileProvider> providers = factory.getProviders(project);
for (JsonSchemaFileProvider provider : providers) {
mySchemaFiles.add(provider.getSchemaFile());
final VirtualFile schemaFile = provider.getSchemaFile();
if (schemaFile != null) {
mySchemaFiles.add(schemaFile);
}
}
}
initialized = true;
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2005 Dave Griffith
* Copyright 2000-2016 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.
@@ -13,20 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.psiutils;
package com.intellij.openapi.vfs;
import com.intellij.psi.PsiAssignmentExpression;
import com.intellij.psi.PsiExpression;
import org.jetbrains.annotations.NotNull;
public class WellFormednessUtils {
private WellFormednessUtils() {
super();
}
public static boolean isWellFormed(@NotNull PsiAssignmentExpression expression) {
final PsiExpression rhs = expression.getRExpression();
return rhs != null;
}
/**
* @author Irina.Chernushina on 7/4/2016.
*/
public interface VirtualFileWithoutContent {
}
@@ -114,4 +114,17 @@ public abstract class ApplicationInfoEx extends ApplicationInfo {
@Nullable
public abstract String getCustomizeIDEWizardStepsProvider();
public abstract String getSubscriptionFormId();
public abstract String getSubscriptionNewsKey();
public abstract String getSubscriptionNewsValue();
public abstract String getSubscriptionTipsKey();
public abstract boolean areSubscriptionTipsAvailable();
@Nullable
public abstract String getSubscriptionAdditionalFormData();
}
@@ -112,6 +112,13 @@ public class ApplicationInfoImpl extends ApplicationInfoEx {
private String myEvalLicenseUrl = "https://www.jetbrains.com/store/license.html";
private String myKeyConversionUrl = "https://www.jetbrains.com/shop/eform/keys-exchange";
private String mySubscriptionFormId;
private String mySubscriptionNewsKey;
private String mySubscriptionNewsValue;
private String mySubscriptionTipsKey;
private boolean mySubscriptionTipsAvailable;
private String mySubscriptionAdditionalFormData;
private Rectangle myAboutLogoRect;
private static final String IDEA_PATH = "/idea/";
@@ -193,6 +200,14 @@ public class ApplicationInfoImpl extends ApplicationInfoEx {
private static final String ATTRIBUTE_KEY_CONVERSION_URL = "key-conversion-url";
private static final String ESSENTIAL_PLUGIN = "essential-plugin";
private static final String ELEMENT_SUBSCRIPTIONS = "subscriptions";
private static final String ATTRIBUTE_SUBSCRIPTIONS_FORM_ID = "formid";
private static final String ATTRIBUTE_SUBSCRIPTIONS_NEWS_KEY = "news-key";
private static final String ATTRIBUTE_SUBSCRIPTIONS_NEWS_VALUE = "news-value";
private static final String ATTRIBUTE_SUBSCRIPTIONS_TIPS_KEY = "tips-key";
private static final String ATTRIBUTE_SUBSCRIPTIONS_TIPS_AVAILABLE = "tips-available";
private static final String ATTRIBUTE_SUBSCRIPTIONS_ADDITIONAL_FORM_DATA = "additional-form-data";
private static final String DEFAULT_PLUGINS_HOST = "http://plugins.jetbrains.com";
ApplicationInfoImpl() {
@@ -554,6 +569,37 @@ public class ApplicationInfoImpl extends ApplicationInfoEx {
return myAboutLogoRect;
}
@Override
public String getSubscriptionFormId() {
return mySubscriptionFormId;
}
@Override
public String getSubscriptionNewsKey() {
return mySubscriptionNewsKey;
}
@Override
public String getSubscriptionNewsValue() {
return mySubscriptionNewsValue;
}
@Override
public String getSubscriptionTipsKey() {
return mySubscriptionTipsKey;
}
@Override
public boolean areSubscriptionTipsAvailable() {
return mySubscriptionTipsAvailable;
}
@Nullable
@Override
public String getSubscriptionAdditionalFormData() {
return mySubscriptionAdditionalFormData;
}
private static ApplicationInfoImpl ourShadowInstance;
public boolean isBetaOrRC() {
@@ -866,6 +912,15 @@ public class ApplicationInfoImpl extends ApplicationInfoEx {
}
}
Element subscriptionsElement = parentNode.getChild(ELEMENT_SUBSCRIPTIONS);
if (subscriptionsElement != null) {
mySubscriptionFormId = subscriptionsElement.getAttributeValue(ATTRIBUTE_SUBSCRIPTIONS_FORM_ID);
mySubscriptionNewsKey = subscriptionsElement.getAttributeValue(ATTRIBUTE_SUBSCRIPTIONS_NEWS_KEY);
mySubscriptionNewsValue = subscriptionsElement.getAttributeValue(ATTRIBUTE_SUBSCRIPTIONS_NEWS_VALUE, "yes");
mySubscriptionTipsKey = subscriptionsElement.getAttributeValue(ATTRIBUTE_SUBSCRIPTIONS_TIPS_KEY);
mySubscriptionTipsAvailable = Boolean.parseBoolean(subscriptionsElement.getAttributeValue(ATTRIBUTE_SUBSCRIPTIONS_TIPS_AVAILABLE));
mySubscriptionAdditionalFormData = subscriptionsElement.getAttributeValue(ATTRIBUTE_SUBSCRIPTIONS_ADDITIONAL_FORM_DATA);
}
}
private static void setBuildNumber(String apiVersion, String buildNumber) {
@@ -23,6 +23,8 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithoutContent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -48,6 +50,10 @@ abstract class BaseShowDiffAction extends AnAction implements DumbAware {
protected abstract boolean isAvailable(@NotNull AnActionEvent e);
protected static boolean hasContent(VirtualFile file) {
return !(file instanceof VirtualFileWithoutContent);
}
@Nullable
protected abstract DiffRequest getDiffRequest(@NotNull AnActionEvent e);
}
@@ -72,7 +72,7 @@ public class CompareFileWithEditorAction extends BaseShowDiffAction {
}
private static boolean canCompare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) {
return file1.isValid() && file2.isValid() && !file1.equals(file2);
return !file1.equals(file2) && hasContent(file1) && hasContent(file2);
}
@Nullable
@@ -83,20 +83,16 @@ public class CompareFilesAction extends BaseShowDiffAction {
}
if (files.length == 1) {
return isValidAndLocal(files[0]);
return hasContent(files[0]);
}
else if (files.length == 2) {
return isValidAndLocal(files[0]) && isValidAndLocal(files[1]);
return hasContent(files[0]) && hasContent(files[1]);
}
else {
return false;
}
}
private static boolean isValidAndLocal(VirtualFile file) {
return file.isValid() && file.isInLocalFileSystem();
}
@Nullable
@Override
protected DiffRequest getDiffRequest(@NotNull AnActionEvent e) {
@@ -110,7 +106,7 @@ public class CompareFilesAction extends BaseShowDiffAction {
if (data.length == 1) {
VirtualFile otherFile = getOtherFile(project, data[0]);
if (otherFile == null) return null;
if (!data[0].isValid()) return null;
if (!hasContent(data[0])) return null;
return DiffRequestFactory.getInstance().createFromFiles(project, data[0], otherFile);
}
else {
@@ -34,6 +34,7 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithoutContent;
import com.intellij.util.LineSeparator;
import com.intellij.util.PathUtil;
import com.intellij.util.TimeoutUtil;
@@ -56,7 +57,11 @@ public class ExternalDiffToolUtil {
public static boolean canCreateFile(@NotNull DiffContent content) {
if (content instanceof EmptyContent) return true;
if (content instanceof DocumentContent) return true;
if (content instanceof FileContent) return true;
if (content instanceof FileContent) {
VirtualFile file = ((FileContent)content).getFile();
if (file instanceof VirtualFileWithoutContent) return false;
return true;
}
if (content instanceof DirectoryContent) return ((DirectoryContent)content).getFile().isInLocalFileSystem();
return false;
}
@@ -34,6 +34,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWithoutContent;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -130,6 +131,7 @@ public class BinaryEditorHolder extends EditorHolder {
if (project == null) project = ProjectManager.getInstance().getDefaultProject();
VirtualFile file = ((FileContent)content).getFile();
if (!file.isValid()) return false;
if (file instanceof VirtualFileWithoutContent) return false;
return FileEditorProviderManager.getInstance().getProviders(project, file).length != 0;
}
return false;
@@ -99,6 +99,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
@CalledInAwt
protected void onDispose() {
destroyChangedBlocks();
myFoldingModel.destroy();
super.onDispose();
}
@@ -225,6 +226,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
private Runnable apply(@NotNull final CompareData data) {
return () -> {
myFoldingModel.updateContext(myRequest, getFoldingModelSettings());
clearDiffPresentation();
myIsContentsEqual = data.isContentsEqual();
@@ -253,6 +255,7 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
private Runnable applyNotification(@Nullable final JComponent notification) {
return () -> {
clearDiffPresentation();
myFoldingModel.destroy();
if (notification != null) myPanel.addNotification(notification);
};
}
@@ -290,8 +293,6 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
}
myInvalidDiffChanges.clear();
myFoldingModel.destroy();
myContentPanel.repaintDivider();
myStatusPanel.update();
}
@@ -88,6 +88,7 @@ public abstract class ThreesideTextDiffViewerEx extends ThreesideTextDiffViewer
@CalledInAwt
protected void onDispose() {
destroyChangedBlocks();
myFoldingModel.destroy();
super.onDispose();
}
@@ -119,6 +120,7 @@ public abstract class ThreesideTextDiffViewerEx extends ThreesideTextDiffViewer
protected Runnable applyNotification(@Nullable final JComponent notification) {
return () -> {
clearDiffPresentation();
myFoldingModel.destroy();
if (notification != null) myPanel.addNotification(notification);
};
}
@@ -135,7 +137,6 @@ public abstract class ThreesideTextDiffViewerEx extends ThreesideTextDiffViewer
@CalledInAwt
protected void destroyChangedBlocks() {
myFoldingModel.destroy();
}
//
@@ -100,12 +100,21 @@ public class FoldingModelSupport {
@NotNull final Settings settings) {
ApplicationManager.getApplication().assertIsDispatchThread();
if (changedLines == null) return;
if (settings.range == -1) return;
for (FoldedBlock folding : getFoldedBlocks()) {
folding.destroyHighlighter();
}
runBatchOperation(() -> {
FoldingBuilder builder = new FoldingBuilder(context, settings);
builder.build(changedLines);
for (FoldedBlock folding : getFoldedBlocks()) {
folding.destroyFolding();
}
myFoldings.clear();
if (changedLines != null && settings.range != -1) {
FoldingBuilder builder = new FoldingBuilder(context, settings);
builder.build(changedLines);
}
});
updateLineNumbers(true);
@@ -244,23 +253,15 @@ public class FoldingModelSupport {
}
public void destroy() {
for (int i = 0; i < myCount; i++) {
destroyFoldings(i);
}
for (FoldedBlock folding : getFoldedBlocks()) {
folding.destroyHighlighter();
}
myFoldings.clear();
}
private void destroyFoldings(final int index) {
final FoldingModelEx model = myEditors[index].getFoldingModel();
model.runBatchFoldingOperation(() -> {
runBatchOperation(() -> {
for (FoldedBlock folding : getFoldedBlocks()) {
FoldRegion region = folding.getRegion(index);
if (region != null) model.removeFoldRegion(region);
folding.destroyFolding();
}
myFoldings.clear();
});
}
@@ -615,6 +616,13 @@ public class FoldingModelSupport {
}
}
public void destroyFolding() {
for (int i = 0; i < myCount; i++) {
FoldRegion region = myRegions[i];
if (region != null) myEditors[i].getFoldingModel().removeFoldRegion(region);
}
}
public void destroyHighlighter() {
for (RangeHighlighter highlighter : myHighlighters) {
highlighter.dispose();
@@ -80,7 +80,7 @@ public class FilenameIndex extends ScalarIndexExtension<String> {
@Override
public int getVersion() {
return 1 + (FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping ? 1 : 0);
return 1 + (FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping ? 2 : 0);
}
public static String[] getAllFilenames(Project project) {
@@ -145,7 +145,7 @@ public class PsiElementListNavigator {
setCancelCallback(() -> {
HintUpdateSupply.hideHint(list);
if (listUpdaterTask != null) {
return listUpdaterTask.cancelTask();
listUpdaterTask.cancelTask();
}
return true;
});
@@ -20,6 +20,7 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingLevelManager;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.IntentionManager;
@@ -311,7 +312,9 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass {
}
}
collectIntentionsFromDoNotShowLeveledInspections(project, hostFile, psiElement, offset, intentions);
if (HighlightingLevelManager.getInstance(project).shouldInspect(hostFile)) {
collectIntentionsFromDoNotShowLeveledInspections(project, hostFile, psiElement, offset, intentions);
}
final int line = hostDocument.getLineNumber(offset);
MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(hostDocument, project, true);
@@ -57,15 +57,14 @@ public class DFAEngine<E> {
final boolean[] visited = new boolean[myFlow.length];
final boolean forward = myDfa.isForward();
final int[] order = ControlFlowUtil.postOrder(myFlow);
// Count limit for number of iterations per worklist
final int limit = getIterationLimit(forward);
final int limit = getIterationLimit();
int dfaCount = 0;
final long startTime = System.nanoTime();
for (int i = forward ? 0 : myFlow.length - 1; forward ? i < myFlow.length : i >= 0; ) {
for (int i = 0; i < myFlow.length; i++) {
// Check if canceled
ProgressManager.checkCanceled();
@@ -124,12 +123,6 @@ public class DFAEngine<E> {
}
// Move to another worklist
if (forward) {
i++;
}
else {
i--;
}
dfaCount += count;
}
if (LOG.isDebugEnabled()) {
@@ -144,10 +137,10 @@ public class DFAEngine<E> {
* Every node in dfa should be processed <= pred times * 2
* Multiplier 2 is because of cycles.
*/
private int getIterationLimit(final boolean forward) {
private int getIterationLimit() {
int allPred = myFlow.length;
for (Instruction instruction : myFlow) {
allPred += forward ? instruction.allPred().size() : instruction.allSucc().size();
allPred += instruction.allPred().size();
}
return allPred * 2;
}
@@ -26,5 +26,8 @@ public interface DfaInstance<E> {
@NotNull
E initial();
/**
* @deprecated
*/
boolean isForward();
}
@@ -184,7 +184,7 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
HintUpdateSupply.hideHint(list);
final ListBackgroundUpdaterTask task = gotoData.listUpdaterTask;
if (task != null) {
return task.cancelTask();
task.cancelTask();
}
return true;
}).
@@ -806,6 +806,15 @@ public class FileBasedIndexImpl extends FileBasedIndex {
: processValuesInScope(indexId, dataKey, false, filter, idFilter, processor);
}
public <K, V> long getIndexModificationStamp(ID<K, V> indexId, @NotNull Project project) {
UpdatableIndex<K, V, FileContent> index = getState().getIndex(indexId);
if (index instanceof MapReduceIndex) {
ensureUpToDate(indexId, project, GlobalSearchScope.allScope(project));
return ((MapReduceIndex)index).getModificationStamp();
}
return -1;
}
public interface IdValueProcessor<V> {
/**
* @param fileId the id of the file that the value came from
@@ -46,6 +46,7 @@ import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -66,6 +67,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
private final boolean myIsPsiBackedIndex;
private final IndexExtension<Key, Value, Input> myExtension;
private final AtomicBoolean myInMemoryMode = new AtomicBoolean();
private final AtomicLong myModificationStamp = new AtomicLong();
private final TIntObjectHashMap<Collection<Key>> myInMemoryKeys = new TIntObjectHashMap<Collection<Key>>();
private PersistentHashMap<Integer, ByteSequence> myContents;
@@ -900,6 +902,10 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
return myExtension;
}
public long getModificationStamp() {
return myModificationStamp.get();
}
public class SimpleUpdateData extends UpdateData<Key, Value> {
private final int savedInputId;
private final @NotNull Map<Key, Value> newData;
@@ -934,6 +940,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
myRemoveStaleKeyOperation = new MapDiffUpdateData.RemovedOrUpdatedKeyProcessor<Key>() {
@Override
public void process(Key key, int inputId) throws StorageException {
myModificationStamp.incrementAndGet();
myStorage.removeAllValues(key, inputId);
}
};
@@ -941,6 +948,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
private final MapDiffUpdateData.AddedKeyProcessor<Key, Value> myAddedKeyProcessor = new MapDiffUpdateData.AddedKeyProcessor<Key, Value>() {
@Override
public void process(Key key, Value value, int inputId) throws StorageException {
myModificationStamp.incrementAndGet();
myStorage.addValue(key, inputId, value);
}
};
@@ -84,10 +84,10 @@ public class ChangeBufferingList implements Cloneable {
}
public void remove(int value) {
ensureCapacity(1);
if (checkSet != null) checkSet.remove(value);
RandomAccessIntContainer intContainer = randomAccessContainer;
if (intContainer == null) {
ensureCapacity(1);
addChange(-value);
}
else {
@@ -44,6 +44,7 @@ import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.*;
import java.lang.reflect.Field;
@@ -937,13 +938,11 @@ public class JBScrollPane extends JScrollPane {
g.fillRoundRect(x, y, width, height, arc, arc);
}
if (myDrawColor != null) {
Path2D path = new Path2D.Double(Path2D.WIND_EVEN_ODD);
path.append(new RoundRectangle2D.Double(x, y, width, height, arc, arc), false);
path.append(new RoundRectangle2D.Double(x + 1, y + 1, width - 2, height - 2, arc - 2, arc - 2), false);
g.setColor(myDrawColor);
if (UIUtil.isRetina(g)) {
g.drawRoundRect(x, y, width, height, arc, arc);
}
else {
g.drawRoundRect(x, y, width - 1, height - 1, arc, arc);
}
g.fill(path);
}
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, old);
}
@@ -88,10 +88,7 @@ public class DefaultIdeaErrorLogger implements ErrorLogger {
}
else if (!ourOomOccurred) {
MessagePool messagePool = MessagePool.getInstance();
LogMessage message = messagePool.addIdeFatalMessage(event);
if (message != null && ApplicationManager.getApplication() != null) {
ErrorNotifier.notifyUi(message, messagePool);
}
messagePool.addIdeFatalMessage(event);
}
}
catch (Throwable e) {
@@ -1,102 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.diagnostic;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.StatusBarWidget;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import java.awt.*;
/**
* @author peter
*/
public class ErrorNotifier {
private static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.logOnlyGroup("IDE Fatal Errors");
public static void notifyUi(final LogMessage message, final MessagePool pool) {
//noinspection ThrowableResultOfMethodCallIgnored
if (message.getThrowable() instanceof MessagePool.TooManyErrorsException) {
NOTIFICATION_GROUP.createNotification(message.getMessage(), NotificationType.ERROR).notify(null);
return;
}
String title = "<a href='xxx'>" + getTitle(message) + "</a>";
String notificationText = getNotificationText(message);
NotificationListener listener = new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
openFatals(event, message);
}
}
};
Notification notification = new Notification(NOTIFICATION_GROUP.getDisplayId(), title, notificationText, NotificationType.ERROR, listener) {
@Override
public void expire() {
super.expire();
if (!message.isRead()) {
message.setRead(true);
}
pool.notifyListenersRead();
}
};
notification.notify(null);
message.setNotification(notification);
}
private static void openFatals(HyperlinkEvent event, LogMessage message) {
Object source = event.getSource();
if (source instanceof Component) {
Window window = SwingUtilities.getWindowAncestor((Component)source);
if (window instanceof IdeFrame) {
final StatusBar statusBar = ((IdeFrame)window).getStatusBar();
StatusBarWidget widget = statusBar == null ? null : statusBar.getWidget(IdeMessagePanel.FATAL_ERROR);
if (widget instanceof IdeMessagePanel) {
((IdeMessagePanel)widget).openFatals(message);
}
}
}
}
private static String getNotificationText(LogMessage message) {
String text = message.getMessage();
if (message instanceof LogMessageEx) {
String result = ((LogMessageEx)message).getNotificationText();
if (result != null) {
text = StringUtil.stripHtml(result, false);
}
}
return text;
}
private static String getTitle(LogMessage message) {
if (message instanceof LogMessageEx) {
return ((LogMessageEx)message).getTitle();
}
@SuppressWarnings("ThrowableResultOfMethodCallIgnored") Throwable throwable = message.getThrowable();
return throwable == null ? "IDE Fatal Error" : throwable.getClass().getSimpleName();
}
}
@@ -27,5 +27,5 @@ import com.intellij.notification.NotificationGroup;
public class ReportMessages {
public static final String ERROR_REPORT = DiagnosticBundle.message("error.report.title");
public static final NotificationGroup GROUP = new NotificationGroup(ERROR_REPORT, NotificationDisplayType.BALLOON, true);
public static final NotificationGroup GROUP = new NotificationGroup(ERROR_REPORT, NotificationDisplayType.BALLOON, false);
}
@@ -122,32 +122,34 @@ public class MacOSApplicationProvider implements ApplicationComponent {
private static class Worker {
public static void initMacApplication() {
Application application = Application.getApplication();
application.setAboutHandler(event -> AboutAction.perform(getProject()));
application.setAboutHandler(event -> AboutAction.perform(getProject(false)));
application.setPreferencesHandler(event -> {
Project project = getNotNullProject();
submit(() -> ShowSettingsAction.perform(project));
Project project = getProject(true);
submit("Preferences", () -> ShowSettingsAction.perform(project));
});
application.setQuitHandler((event, response) -> {
submit(ExitAction::perform);
submit("Quit", ExitAction::perform);
response.cancelQuit();
});
application.setOpenFileHandler(event -> {
Project project = getProject();
Project project = getProject(false);
List<File> list = event.getFiles();
LOG.debug("MacMenu: files found ", list.size());
if (list.isEmpty()) return;
File file = list.get(0);
submit(() -> {
LOG.debug("MacMenu: try to open file");
if (ProjectUtil.openOrImport(file.getAbsolutePath(), project, true) != null) {
LOG.debug("MacMenu: load project for ", file);
IdeaApplication.getInstance().setPerformProjectLoad(false);
return;
submit("OpenFile", () -> {
for (File file : list) {
if (ProjectUtil.openOrImport(file.getAbsolutePath(), project, true) != null) {
LOG.debug("MacMenu: load project from ", file);
IdeaApplication.getInstance().setPerformProjectLoad(false);
return;
}
}
LOG.debug("MacMenu: project = ", project);
if (project != null && file.exists()) {
LOG.debug("MacMenu: open file ", file);
OpenFileAction.openFile(file.getAbsolutePath(), project);
if (project != null) {
for (File file : list) {
if (file.exists()) {
LOG.debug("MacMenu: open file ", file);
OpenFileAction.openFile(file.getAbsolutePath(), project);
}
}
}
});
});
@@ -179,33 +181,49 @@ public class MacOSApplicationProvider implements ApplicationComponent {
Foundation.invoke(pool, Foundation.createSelector("release"));
}
@SuppressWarnings("deprecation")
private static Project getProject() {
return CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
private static Project getProject(boolean useDefault) {
@SuppressWarnings("deprecation")
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
if (project == null) {
LOG.debug("MacMenu: no project in data context");
Project[] projects = ProjectManager.getInstance().getOpenProjects();
project = projects.length > 0 ? projects[0] : null;
if (project == null && useDefault) {
LOG.debug("MacMenu: use default project instead");
project = ProjectManager.getInstance().getDefaultProject();
}
}
LOG.debug("MacMenu: project = ", project);
return project;
}
@NotNull
private static Project getNotNullProject() {
Project project = getProject();
return project != null ? project : ProjectManager.getInstance().getDefaultProject();
}
private static void submit(@NotNull Runnable task) {
private static void submit(@NotNull String name, @NotNull Runnable task) {
LOG.debug("MacMenu: on EDT = ", SwingUtilities.isEventDispatchThread(), "; ENABLED = ", ENABLED.get());
if (!ENABLED.get()) return;
Component component = IdeFocusManager.getGlobalInstance().getFocusOwner();
if (component == null || IdeKeyEventDispatcher.isModalContext(component)) return;
ENABLED.set(false);
TransactionGuard.submitTransaction(ApplicationManager.getApplication(), () -> {
try {
task.run();
if (!ENABLED.get()) {
LOG.debug("MacMenu: disabled");
}
else {
Component component = IdeFocusManager.getGlobalInstance().getFocusOwner();
if (component == null) {
LOG.debug("MacMenu: no focused component");
}
finally {
ENABLED.set(true);
else if (IdeKeyEventDispatcher.isModalContext(component)) {
LOG.debug("MacMenu: component in modal context");
}
});
else {
ENABLED.set(false);
TransactionGuard.submitTransaction(ApplicationManager.getApplication(), () -> {
try {
LOG.debug("MacMenu: init ", name);
task.run();
}
finally {
LOG.debug("MacMenu: done ", name);
ENABLED.set(true);
}
});
}
}
}
}
}
@@ -19,6 +19,7 @@ import com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.ui.Gray;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.border.Border;
@@ -52,9 +53,10 @@ public class WinIntelliJButtonPainter implements Border, UIResource {
g.translate(x,y);
if (hasFocus) {
g.setStroke(new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1, new float[]{1}, 1));
//g.setStroke(new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1, new float[]{1}, 1));
g.setColor(Gray.x0F);
g.drawRect(2*dd, 2*dd, width - 4*dd - 1, height - 4*dd - 1);
UIUtil.drawDottedRectangle(g, 2*dd, 2*dd, width - 2*dd - 1, height - 2*dd - 1);
//g.drawRect(2*dd, 2*dd, width - 4*dd - 1, height - 4*dd - 1);
}
g.translate(-x,-y);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -40,11 +40,11 @@ import org.jetbrains.annotations.Nullable;
public final class StoreUtil {
private static final Logger LOG = Logger.getInstance(StoreUtil.class);
private StoreUtil() {
}
private StoreUtil() { }
public static void save(@NotNull IComponentStore stateStore, @Nullable Project project) {
ShutDownTracker.getInstance().registerStopperThread(Thread.currentThread());
Thread currentThread = Thread.currentThread();
ShutDownTracker.getInstance().registerStopperThread(currentThread);
try {
stateStore.save(new SmartList<Pair<SaveSession, VirtualFile>>());
}
@@ -77,7 +77,7 @@ public final class StoreUtil {
}
}
finally {
ShutDownTracker.getInstance().unregisterStopperThread(Thread.currentThread());
ShutDownTracker.getInstance().unregisterStopperThread(currentThread);
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 2000-2016 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.roots;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public class ProjectRootUtil {
@NotNull
public static VirtualFile findSymlinkedFileInContent(@NotNull Project project, @NotNull VirtualFile forFile) {
GlobalSearchScope scope = GlobalSearchScope.allScope(project);
if (scope.contains(forFile)) return forFile;
Collection<VirtualFile> projectFiles =
FilenameIndex.getVirtualFilesByName(project, forFile.getName(), true, scope);
for (VirtualFile eachContentFile : projectFiles) {
if (forFile.equals(eachContentFile.getCanonicalFile())) return eachContentFile;
}
return forFile;
}
}
@@ -16,6 +16,7 @@
package com.intellij.ui;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.laf.darcula.ui.DarculaEditorTextFieldBorder;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataProvider;
@@ -562,7 +563,10 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
if (myInheritSwingFont) {
editor.getColorsScheme().setEditorFontName(getFont().getFontName());
editor.getColorsScheme().setEditorFontSize(getFont().getSize());
return;
}
UISettings settings = UISettings.getInstance();
if (settings.PRESENTATION_MODE) editor.setFontSize(settings.PRESENTATION_MODE_FONT_SIZE);
}
protected boolean shouldHaveBorder() {
@@ -168,8 +168,6 @@ intention.join.declaration.family=Join Declaration and Assignment
intention.split.declaration.text=Split into separate declarations
intention.join.declaration.text=Join declaration and assignment
intention.split.declaration.assignment.text=Split into declaration and assignment
intention.add.override.annotation=Add '@Override' annotation
intention.add.override.annotation.family=Add Override Annotation
intention.split.if.family=Split If
intention.split.if.text=Split into 2 if's
intention.split.filter.text=Split into filter's chain
@@ -54,7 +54,7 @@ incorrect.name=Incorrect name
jrt.node.short=[JRT]
jrt.node.long=[Java Run-time Modules]
jrt.not.available.message=You need to run IDEA on Java 8 to be able to use modular JDK. Sorry.
jrt.not.available.message=You need to run IDEA on Java 8+ to be able to use modular JDK. Sorry.
jrt.not.available.title=Unsupported JDK ''{0}'' detected
compound.run.configuration.cycle={0} ''{1}'' causes dependency cycle and cannot be added
@@ -0,0 +1,147 @@
/*
* Copyright 2000-2016 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.roots;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.IoTestUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.PsiTestUtil;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
public class ProjectRootUtilSymlinkedFilesTest extends PlatformTestCase {
private File myCanonicalDir;
private File myCanonicalFile;
private VirtualFile myCanonicalVFile;
private File myContentDir;
private VirtualFile myContentVDir;
private File myLibraryDir;
private VirtualFile myLibraryVDir;
@Override
protected boolean shouldRunTest() {
return super.shouldRunTest() && SystemInfo.areSymLinksSupported;
}
@Override
public void setUp() throws Exception {
super.setUp();
myCanonicalDir = FileUtil.createTempDirectory("canonical", null);
myCanonicalFile = new File(myCanonicalDir, "foo.txt");
assertTrue(myCanonicalFile.createNewFile());
myCanonicalVFile = VfsUtil.findFileByIoFile(myCanonicalFile, true);
assertNotNull(myCanonicalVFile);
myContentDir = FileUtil.createTempDirectory("content", null);
myContentVDir = VfsUtil.findFileByIoFile(myContentDir, true);
assertNotNull(myContentVDir);
PsiTestUtil.addContentRoot(getModule(), myContentVDir);
myLibraryDir = FileUtil.createTempDirectory("library", null);
myLibraryVDir = VfsUtil.findFileByIoFile(myLibraryDir, true);
assertNotNull(myLibraryVDir);
PsiTestUtil.addLibrary(getModule(), myLibraryVDir.getPath());
}
public void testNoFilesInContent() throws Exception {
assertEquals(myCanonicalVFile, ProjectRootUtil.findSymlinkedFileInContent(getProject(), myCanonicalVFile));
}
public void testLinkedDirInContent() throws Exception {
doTestLinkedDirInProjectRoots(true);
}
public void testLinkedDirInLibrary() throws Exception {
doTestLinkedDirInProjectRoots(false);
}
public void doTestLinkedDirInProjectRoots(boolean content) throws Exception {
String linkedPath = (content ? myContentDir : myLibraryDir).getPath() + "/linked";
IoTestUtil.createSymLink(myCanonicalDir.getPath(), linkedPath, true);
VirtualFile linkedVFile = VfsUtil.findFileByIoFile(new File(linkedPath, myCanonicalFile.getName()), true);
assertEquals(linkedVFile, ProjectRootUtil.findSymlinkedFileInContent(getProject(), myCanonicalVFile));
}
// not supported
public void _testLinkedFileInSources() throws Exception {
String linkedPath = myContentDir.getPath() + "/linked.txt";
IoTestUtil.createSymLink(myCanonicalVFile.getPath(), linkedPath, true);
VirtualFile linkedVFile = VfsUtil.findFileByIoFile(new File(linkedPath), true);
assertEquals(linkedVFile, ProjectRootUtil.findSymlinkedFileInContent(getProject(), myCanonicalVFile));
}
public void testFileWithTheSameNotButNotLinked() throws Exception {
new WriteAction<Object>() {
@Override
protected void run(@NotNull Result<Object> result) throws Throwable {
myContentVDir.createChildData(this, myCanonicalFile.getName());
}
}.execute();
assertEquals(myCanonicalVFile, ProjectRootUtil.findSymlinkedFileInContent(getProject(), myCanonicalVFile));
}
public void testWhenSeveralLinkedAlwaysReturnTheSameFile() throws Exception {
String linkedPath1 = myContentDir.getPath() + "/linked1";
IoTestUtil.createSymLink(myCanonicalDir.getPath(), linkedPath1, true);
VirtualFile linkedVFile1 = VfsUtil.findFileByIoFile(new File(linkedPath1, myCanonicalFile.getName()), true);
assertNotNull(linkedVFile1);
String linkedPath2 = myContentDir.getPath() + "/linked2";
IoTestUtil.createSymLink(myCanonicalDir.getPath(), linkedPath2, true);
VirtualFile linkedVFile2 = VfsUtil.findFileByIoFile(new File(linkedPath2, myCanonicalFile.getName()), true);
assertNotNull(linkedVFile2);
VirtualFile found = ProjectRootUtil.findSymlinkedFileInContent(getProject(), myCanonicalVFile);
assertTrue(found.equals(linkedVFile1) || found.equals(linkedVFile2));
for(int i = 0; i < 10; i++) {
assertEquals("try: " + i, found, ProjectRootUtil.findSymlinkedFileInContent(getProject(), myCanonicalVFile));
}
}
public void testLinkedAndCanonicalUnderContent() throws Exception {
doTestLinkedAndCanonicalUnderRoot(true);
}
public void testLinkedAndCanonicalUnderLibraryRoot() throws Exception {
doTestLinkedAndCanonicalUnderRoot(false);
}
private void doTestLinkedAndCanonicalUnderRoot(boolean content) throws InterruptedException, IOException {
String linkedPath = myContentDir.getPath() + "/linked";
IoTestUtil.createSymLink(myCanonicalDir.getPath(), linkedPath, true);
VirtualFile linkedVFile = VfsUtil.findFileByIoFile(new File(linkedPath, myCanonicalFile.getName()), true);
assertEquals(linkedVFile, ProjectRootUtil.findSymlinkedFileInContent(getProject(), myCanonicalVFile));
if(content) {
PsiTestUtil.addContentRoot(getModule(), myCanonicalVFile.getParent());
} else {
PsiTestUtil.addLibrary(getModule(), myCanonicalVFile.getParent().getPath());
}
assertEquals(myCanonicalVFile, ProjectRootUtil.findSymlinkedFileInContent(getProject(), myCanonicalVFile));
}
}
@@ -44,9 +44,9 @@ class ScopeVariablesGroup(val scope: Scope, parentContext: VariableContext, call
promise
.done(node) {
context.memberFilter
.thenAsyncAccept(node) { memberFilter ->
if (memberFilter.hasNameMappings()) {
memberFilter.sourceNameToRaw(RECEIVER_NAME)?.let {
.thenAsyncAccept(node) {
if (it.hasNameMappings()) {
it.sourceNameToRaw(RECEIVER_NAME)?.let {
return@thenAsyncAccept callFrame.evaluateContext.evaluate(it)
.done(node) {
VariableImpl(RECEIVER_NAME, it.value, null)
@@ -29,6 +29,6 @@ internal class VariablesGroup(private val start: Int, private val end: Int, priv
}
internal fun createArrayRangeGroup(variables: List<Variable>, start: Int, end: Int, variableContext: VariableContext): VariablesGroup {
val name = "[" + variables[start].name + " \u2026 " + variables[end - 1].name + "]"
val name = "[${variables[start].name} \u2026 ${variables[end - 1].name}]"
return VariablesGroup(start, end, variables, variableContext, name)
}
@@ -40,7 +40,8 @@ open class NameMapper(private val document: Document, private val transpiledDocu
// PsiNamedElement, JSVariable for example
// returns generated name
open fun map(identifierOrNamedElement: PsiElement): String? {
@JvmOverloads
open fun map(identifierOrNamedElement: PsiElement, forceMapBySourceCode: Boolean = false): String? {
val offset = identifierOrNamedElement.textOffset
val line = document.getLineNumber(offset)
@@ -67,7 +68,7 @@ open class NameMapper(private val document: Document, private val transpiledDocu
}
var sourceName = sourceEntry.name
if (sourceName == null || (Registry.`is`("js.debugger.name.mappings.by.source.code", false) || Registry.`is`("js.debugger.map.this.by.source.code", false))) {
if (sourceName == null || forceMapBySourceCode || Registry.`is`("js.debugger.name.mappings.by.source.code", false)) {
sourceName = (identifierOrNamedElement as? PsiNamedElement)?.name ?: identifierOrNamedElement.text ?: sourceName ?: return null
}
@@ -537,6 +537,8 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
void testFoldingWithCollapseStatus(@NotNull String fileName);
void testRainbow(@NotNull String fileName, @NotNull String text, boolean isRainbowOn, boolean withColor);
void assertPreferredCompletionItems(int selected, @NotNull String... expected);
/**
@@ -16,6 +16,7 @@
package com.intellij.testFramework.fixtures.impl;
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeHighlighting.RainbowHighlighter;
import com.intellij.codeInsight.TargetElementUtil;
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
import com.intellij.codeInsight.completion.CompletionProgressIndicator;
@@ -70,6 +71,7 @@ import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.editor.impl.DocumentMarkupModel;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.ExtensionsArea;
@@ -83,6 +85,8 @@ import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.registry.RegistryValue;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.profile.Profile;
@@ -133,6 +137,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
private static final String START_FOLD = "<fold\\stext=\'[^\']*\'(\\sexpand=\'[^\']*\')*>";
private static final String END_FOLD = "</fold>";
private static final String RAINBOW = "rainbow";
private final IdeaProjectTestFixture myProjectFixture;
private final TempDirTestFixture myTempDirFixture;
@@ -966,7 +971,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
Assert.assertNotNull("Cannot find handler for: " + targetElement, handler);
final PsiElement[] psiElements = ArrayUtil.mergeArrays(handler.getPrimaryElements(), handler.getSecondaryElements());
final FindUsagesOptions options = handler.getFindUsagesOptions(null);
if (scope != null) options.searchScope = scope;
if (scope != null) options.searchScope = scope;
for (PsiElement psiElement : psiElements) {
handler.processElementUsages(psiElement, processor, options);
}
@@ -1441,7 +1446,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
private PsiFile configureByFileInner(@NotNull VirtualFile copy) {
return configureInner(copy, SelectionAndCaretMarkupLoader.fromFile(copy));
}
private PsiFile configureInner(@NotNull final VirtualFile copy, @NotNull final SelectionAndCaretMarkupLoader loader) {
assertInitialized();
@@ -1750,17 +1755,35 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
}
@NotNull
public String getHighlightingDescription(@NotNull List<HighlightInfo> highlighting, @NotNull String tagName) {
public String getHighlightingDescription(@NotNull List<HighlightInfo> highlighting, @NotNull String tagName, boolean withColor) {
final List<Border> borders = new LinkedList<Border>();
for (HighlightInfo region : highlighting) {
borders.add(new Border(Border.LEFT, region.getStartOffset(), "", false));
TextAttributes attributes = region.getTextAttributes(null, null);
borders.add(new Border(Border.LEFT, region.getStartOffset(),
attributes == null ? "null"
: attributes.getForegroundColor() == null
? "null"
: Integer.toHexString(attributes.getForegroundColor().getRGB()),
false));
borders.add(new Border(Border.RIGHT, region.getEndOffset(), "", false));
}
Collections.sort(borders);
StringBuilder result = new StringBuilder(myEditor.getDocument().getText());
for (Border border : borders) {
result.insert(border.getOffset(), (border.isSide() == Border.LEFT ? "<": "</") + tagName + ">");
StringBuilder info = new StringBuilder();
info.append('<');
if (border.isSide() == Border.LEFT) {
info.append(tagName);
if (withColor) {
info.append(" color=\'").append(border.myText).append('\'');
}
}
else {
info.append('/').append(tagName);
}
info.append('>');
result.insert(border.getOffset(), info);
}
return result.toString();
@@ -1809,6 +1832,23 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
testFoldingRegions(verificationFileName, null, false);
}
@Override
public void testRainbow(@NotNull String fileName, @NotNull String text, boolean isRainbowOn, boolean withColor) {
RegistryValue registryValue = Registry.get("editor.rainbow.identifiers");
final boolean rainbowColors = registryValue.asBoolean();
try {
registryValue.setValue(isRainbowOn);
configureByText(fileName, text.replaceAll("<" + RAINBOW + "(\\scolor=\'[^\']*\')?>", "").replace("</" + RAINBOW + ">", ""));
Assert.assertEquals(text, getHighlightingDescription(ContainerUtil.filter(doHighlighting(),
info -> info.type == RainbowHighlighter.RAINBOW_ELEMENT), RAINBOW,
withColor));
}
finally {
registryValue.setValue(rainbowColors);
}
}
@Override
public void assertPreferredCompletionItems(final int selected, @NotNull final String... expected) {
final LookupImpl lookup = getLookup();
@@ -605,7 +605,7 @@ js.debugger.v8.use.any.breakpoint=true
js.debugger.chrome.use.any.breakpoint=true
nodejs.debugger.use.jb.support=true
js.debugger.name.mappings.by.source.code=false
js.debugger.map.this.by.source.code=false
js.debugger.map.this.by.source.code=true
js.debugger.v8.log=
js.debugger.wip.log=
js.debugger.fix.jspm.source.maps=false
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -75,10 +75,6 @@ public class DateFormatUtil {
private DateFormatUtil() { }
/** @deprecated use {@link #getIso8601Format()} (to be removed in IDEA 16) */
@SuppressWarnings("unused")
public static final SyncDateFormat ISO8601_DATE_FORMAT = ISO8601_FORMAT;
public static long getDifferenceInDays(@NotNull Date startDate, @NotNull Date endDate) {
return (endDate.getTime() - startDate.getTime() + DAY_FACTOR - 1000) / DAY_FACTOR;
}
@@ -398,9 +398,19 @@ public class LineStatusTracker {
}
private class MyApplicationListener extends ApplicationAdapter {
private int myWriteActionDepth = 0;
@Override
public void writeActionStarted(@NotNull Object action) {
myWriteActionDepth++;
}
@Override
public void writeActionFinished(@NotNull Object action) {
updateRanges();
myWriteActionDepth = Math.max(myWriteActionDepth - 1, 0);
if (myWriteActionDepth == 0) {
updateRanges();
}
}
}
@@ -775,7 +775,7 @@ public class XDebugSessionImpl implements XDebugSession {
updateExecutionPosition();
if (myShowTabOnSuspend.compareAndSet(true, false)) {
UIUtil.invokeLaterIfNeeded(() -> {
AppUIUtil.invokeLaterIfProjectAlive(myProject, () -> {
initSessionTab(null);
showSessionTab();
});
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2016 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,19 +17,16 @@ package com.siyeh.ig.abstraction;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.SearchScope;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.CollectionUtils;
import com.siyeh.ig.psiutils.DeclarationSearchUtils;
import com.siyeh.ig.psiutils.LibraryUtil;
import com.siyeh.ig.psiutils.WeakestTypeFinder;
import org.jetbrains.annotations.NotNull;
@@ -146,7 +143,7 @@ public class DeclareCollectionAsInterfaceInspection extends BaseInspection {
@Override
public void visitVariable(@NotNull PsiVariable variable) {
if (isOnTheFly() && !isCheapEnoughToSearch(variable)) {
if (isOnTheFly() && DeclarationSearchUtils.isTooExpensiveToSearch(variable, false)) {
return;
}
if (ignoreLocalVariables && variable instanceof PsiLocalVariable) {
@@ -189,7 +186,7 @@ public class DeclareCollectionAsInterfaceInspection extends BaseInspection {
method.hasModifierProperty(PsiModifier.PRIVATE)) {
return;
}
if (isOnTheFly() && !isCheapEnoughToSearch(method)) {
if (isOnTheFly() && DeclarationSearchUtils.isTooExpensiveToSearch(method, false)) {
return;
}
final PsiType type = method.getReturnType();
@@ -234,20 +231,5 @@ public class DeclareCollectionAsInterfaceInspection extends BaseInspection {
registerError(nameElement, qualifiedName);
}
}
private boolean isCheapEnoughToSearch(PsiNamedElement element) {
final String name = element.getName();
if (name == null) {
return false;
}
final ProgressManager progressManager =
ProgressManager.getInstance();
final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(element.getProject());
final SearchScope useScope = element.getUseScope();
if (useScope instanceof GlobalSearchScope) {
return searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, null, progressManager.getProgressIndicator()) != PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES;
}
return true;
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2005-2012 Bas Leijdekkers
* Copyright 2005-2016 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,18 +16,15 @@
package com.siyeh.ig.abstraction;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Processor;
import com.intellij.util.Query;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.DeclarationSearchUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -182,17 +179,10 @@ public class MethodOnlyUsedFromInnerClassInspection extends BaseInspection {
}
public boolean isOnlyAccessedFromInnerClass() {
final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(method.getProject());
final ProgressManager progressManager = ProgressManager.getInstance();
final ProgressIndicator progressIndicator = progressManager.getProgressIndicator();
final PsiSearchHelper.SearchCostResult searchCost =
searchHelper.isCheapEnoughToSearch(method.getName(), method.getResolveScope(), null, progressIndicator);
if (searchCost == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES ||
searchCost == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES) {
return onlyAccessedFromInnerClass;
if (DeclarationSearchUtils.isTooExpensiveToSearch(method, true)) {
return false;
}
final Query<PsiReference> query = ReferencesSearch.search(method);
query.forEach(this);
ReferencesSearch.search(method).forEach(this);
return onlyAccessedFromInnerClass;
}
@@ -18,9 +18,7 @@ package com.siyeh.ig.abstraction;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.searches.MethodReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
@@ -30,6 +28,7 @@ import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.DeclarationSearchUtils;
import com.siyeh.ig.psiutils.TestUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -110,17 +109,12 @@ public class StaticMethodOnlyUsedInOneClassInspectionBase extends BaseInspection
*/
@Nullable
public PsiClass getUsageClass(final PsiMethod method) {
final ProgressManager progressManager = ProgressManager.getInstance();
final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(method.getProject());
final String name = method.getName();
final GlobalSearchScope scope = GlobalSearchScope.projectScope(method.getProject());
if (searchHelper.isCheapEnoughToSearch(name, scope, null, progressManager.getProgressIndicator())
== PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) {
if (DeclarationSearchUtils.isTooExpensiveToSearch(method, true)) {
return null;
}
progressManager.runProcess(() -> {
ProgressManager.getInstance().runProcess(() -> {
final Query<PsiReference> query = MethodReferencesSearch.search(method);
if (!query.forEach(UsageProcessor.this)) {
if (!query.forEach(this)) {
foundClass.set(null);
}
}, null);
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2016 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.ExtractParameterAsLocalVariableFix;
import com.siyeh.ig.psiutils.WellFormednessUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -79,10 +78,9 @@ public class AssignmentToForLoopParameterInspection
extends BaseInspectionVisitor {
@Override
public void visitAssignmentExpression(
@NotNull PsiAssignmentExpression expression) {
public void visitAssignmentExpression(@NotNull PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
if (!WellFormednessUtils.isWellFormed(expression)) {
if (expression.getRExpression() == null) {
return;
}
final PsiExpression lhs = expression.getLExpression();
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2016 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,12 @@
package com.siyeh.ig.bugs;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.MethodUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NotNull;
@@ -71,25 +73,14 @@ public class CovariantEqualsInspection extends BaseInspection {
}
final PsiMethod[] methods = aClass.getMethods();
for (PsiMethod method1 : methods) {
if (isNonVariantEquals(method1)) {
if (MethodUtils.isEquals(method1)) {
return;
}
}
if (SuperMethodsSearch.search(method, null, true, false).findFirst() != null) {
return;
}
registerMethodError(method);
}
private static boolean isNonVariantEquals(PsiMethod method) {
final String name = method.getName();
if (!HardcodedMethodConstants.EQUALS.equals(name)) {
return false;
}
final PsiParameterList paramList = method.getParameterList();
final PsiParameter[] parameters = paramList.getParameters();
if (parameters.length != 1) {
return false;
}
final PsiType argType = parameters[0].getType();
return TypeUtils.isJavaLangObject(argType);
}
}
}
@@ -257,8 +257,8 @@ public class OptionalGetWithoutIsPresentInspection extends BaseInspection {
}
else if (expression instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
final PsiExpression definition = VariableSearchUtils.findDefinition(referenceExpression, null);
final PsiExpression optionalDefinition = VariableSearchUtils.findDefinition(this.referenceExpression, null);
final PsiExpression definition = DeclarationSearchUtils.findDefinition(referenceExpression, null);
final PsiExpression optionalDefinition = DeclarationSearchUtils.findDefinition(this.referenceExpression, null);
if (definition == null || optionalDefinition == null || optionalDefinition.getTextOffset() > definition.getTextOffset()) {
return false;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2016 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.VariableSearchUtils;
import com.siyeh.ig.psiutils.DeclarationSearchUtils;
import org.jetbrains.annotations.NotNull;
public class ConstantIfStatementInspection extends BaseInspection {
@@ -116,7 +116,7 @@ public class ConstantIfStatementInspection extends BaseInspection {
final PsiCodeBlock block =
((PsiBlockStatement)branch).getCodeBlock();
final boolean hasConflicts =
VariableSearchUtils.containsConflictingDeclarations(
DeclarationSearchUtils.containsConflictingDeclarations(
block, parentBlock);
if (hasConflicts) {
final String elseText = branch.getText();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -26,7 +26,7 @@ import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import com.siyeh.ig.psiutils.VariableSearchUtils;
import com.siyeh.ig.psiutils.DeclarationSearchUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -162,7 +162,7 @@ public class UnnecessaryInitCauseInspectionBase extends BaseInspection {
}
else if (expression instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
final PsiExpression definition = VariableSearchUtils.findDefinition(referenceExpression, null);
final PsiExpression definition = DeclarationSearchUtils.findDefinition(referenceExpression, null);
if (!(definition instanceof PsiNewExpression)) {
return null;
}
@@ -18,10 +18,9 @@ package com.siyeh.ig.fixes;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.VariableSearchUtils;
import com.siyeh.ig.psiutils.DeclarationSearchUtils;
import org.jetbrains.annotations.NotNull;
/**
@@ -53,7 +52,7 @@ public class DeleteCatchSectionFix extends InspectionGadgetsFix {
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiElement parent = element.getParent();
if (!(parent instanceof PsiParameter)) {
@@ -75,7 +74,7 @@ public class DeleteCatchSectionFix extends InspectionGadgetsFix {
final boolean keepBlock;
if (containingElement instanceof PsiCodeBlock) {
final PsiCodeBlock parentBlock = (PsiCodeBlock)containingElement;
keepBlock = VariableSearchUtils.containsConflictingDeclarations(codeBlock, parentBlock);
keepBlock = DeclarationSearchUtils.containsConflictingDeclarations(codeBlock, parentBlock);
}
else {
keepBlock = true;
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2008 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2016 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@ import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.WellFormednessUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -194,9 +193,6 @@ public class MultiplyOrDivideByPowerOfTwoInspection
@Override
public void visitAssignmentExpression(@NotNull PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
if (!WellFormednessUtils.isWellFormed(expression)) {
return;
}
final IElementType tokenType = expression.getOperationTokenType();
if (!tokenType.equals(JavaTokenType.ASTERISKEQ)) {
if (!checkDivision || !tokenType.equals(JavaTokenType.DIVEQ)) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -210,7 +210,7 @@ public abstract class MisorderedAssertEqualsArgumentsInspectionBase extends Base
}
else if (target instanceof PsiLocalVariable) {
final PsiVariable variable = (PsiLocalVariable)target;
final PsiExpression definition = VariableSearchUtils.findDefinition(referenceExpression, variable);
final PsiExpression definition = DeclarationSearchUtils.findDefinition(referenceExpression, variable);
if (LibraryUtil.isOnlyLibraryCodeUsed(definition)) {
return true;
}

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