mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -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.
|
||||
|
||||
+4
-3
@@ -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);
|
||||
|
||||
+7
-5
@@ -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),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+20
-3
@@ -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 { }
|
||||
+48
-5
@@ -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));
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
-168
@@ -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;
|
||||
|
||||
+13
@@ -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);
|
||||
}
|
||||
+1
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -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) {}
|
||||
}
|
||||
}
|
||||
+8
@@ -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";
|
||||
|
||||
+12
-8
@@ -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;
|
||||
|
||||
+6
-16
@@ -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 {
|
||||
|
||||
+6
-1
@@ -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();
|
||||
}
|
||||
|
||||
+2
-1
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -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);
|
||||
}
|
||||
|
||||
+5
-5
@@ -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
|
||||
|
||||
+147
@@ -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)
|
||||
}
|
||||
|
||||
+3
-2
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
+45
-5
@@ -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();
|
||||
});
|
||||
|
||||
+4
-22
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-15
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+4
-10
@@ -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);
|
||||
|
||||
+3
-5
@@ -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();
|
||||
|
||||
+7
-16
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
+3
-3
@@ -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();
|
||||
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
|
||||
+3
-4
@@ -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 +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)) {
|
||||
|
||||
+2
-2
@@ -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
Reference in New Issue
Block a user