Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2015-11-05 18:20:11 +01:00
37 changed files with 406 additions and 314 deletions
@@ -37,6 +37,8 @@ public interface RecentTestRunner {
void run(Location location);
Location getLocation(String url);
boolean isSuite(String url);
}
class RecentTestRunnerImpl implements RecentTestRunner {
@@ -75,6 +77,12 @@ class RecentTestRunnerImpl implements RecentTestRunner {
return null;
}
@Override
public boolean isSuite(String url) {
String protocol = VirtualFileManager.extractProtocol(url);
return JavaTestLocator.SUITE_PROTOCOL.equals(protocol);
}
public void run(final Location location) {
DataContext data = new DataContext() {
@Nullable
@@ -19,7 +19,6 @@ import com.intellij.execution.Location;
import com.intellij.execution.TestStateStorage;
import com.intellij.execution.testframework.TestIconMapper;
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.vfs.VirtualFileManager;
@@ -27,32 +26,81 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.*;
public class SelectTestStep extends BaseListPopupStep<String> {
private static Comparator<String> TEST_BY_PATH_COMPARATOR = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
String path1 = VirtualFileManager.extractPath(o1);
String path2 = VirtualFileManager.extractPath(o2);
return path1.compareTo(path2);
}
};
private final Map<String, TestStateStorage.Record> myRecords;
private final RecentTestRunner myRunner;
public SelectTestStep(Map<String, TestStateStorage.Record> records, RecentTestRunner runner) {
super("Debug Recent Tests", getUrls(records));
super("Debug Recent Tests", getUrls(records, runner));
myRunner = runner;
myRecords = records;
}
private static List<String> getUrls(Map<String, TestStateStorage.Record> records) {
List<String> list = ContainerUtil.newArrayList(records.keySet());
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
String path1 = VirtualFileManager.extractPath(o1);
String path2 = VirtualFileManager.extractPath(o2);
return path1.compareTo(path2);
private static List<String> getUrls(Map<String, TestStateStorage.Record> records, RecentTestRunner runner) {
TestGroup groups = toTestGroups(records, runner);
List<String> failed = ContainerUtil.newArrayList(groups.failedTests);
Collections.sort(failed, TEST_BY_PATH_COMPARATOR);
List<String> other = ContainerUtil.newArrayList(groups.otherTests);
Collections.sort(other, TEST_BY_PATH_COMPARATOR);
List<String> passed = ContainerUtil.newArrayList(groups.passedTests);
Collections.sort(passed, TEST_BY_PATH_COMPARATOR);
failed.addAll(other);
failed.addAll(passed);
return failed;
}
private static TestGroup toTestGroups(Map<String, TestStateStorage.Record> records, RecentTestRunner runner) {
Set<String> failedTests = ContainerUtil.newHashSet();
Set<String> passedSuites = ContainerUtil.newHashSet();
Set<String> otherSuites = ContainerUtil.newHashSet();
for (Map.Entry<String, TestStateStorage.Record> item : records.entrySet()) {
String url = item.getKey();
TestStateInfo.Magnitude magnitude = getMagnitude(item.getValue().magnitude);
if (magnitude == null) continue;
switch (magnitude) {
case COMPLETE_INDEX:
if (runner.isSuite(url)) {
passedSuites.add(url);
}
break;
case PASSED_INDEX:
if (runner.isSuite(url)) {
passedSuites.add(url);
}
break;
case ERROR_INDEX:
failedTests.add(url);
break;
default:
otherSuites.add(url);
break;
}
});
return list;
}
return new TestGroup(failedTests, passedSuites, otherSuites);
}
private static TestStateInfo.Magnitude getMagnitude(int magnitude) {
for (TestStateInfo.Magnitude m : TestStateInfo.Magnitude.values()) {
if (m.getValue() == magnitude) {
return m;
}
}
return null;
}
@NotNull
@@ -79,4 +127,16 @@ public class SelectTestStep extends BaseListPopupStep<String> {
myRunner.run(location);
return null;
}
private static class TestGroup {
public Set<String> failedTests;
public Set<String> passedTests;
public Set<String> otherTests;
public TestGroup(Set<String> failedTests, Set<String> passedTests, Set<String> otherTests) {
this.failedTests = failedTests;
this.passedTests = passedTests;
this.otherTests = otherTests;
}
}
}
@@ -24,7 +24,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.ListPopupStep;
import com.intellij.ui.popup.list.ListPopupImpl;
import com.intellij.util.PsiNavigateUtil;
import com.intellij.util.Time;
import javax.swing.*;
import java.awt.event.ActionEvent;
@@ -33,10 +32,10 @@ import java.util.Date;
import java.util.Map;
public class ShowRecentTests extends AnAction {
private static final int TEST_LIMIT = 20;
private static final int TEST_LIMIT = Integer.MAX_VALUE;
private static Date getSinceDate() {
return new Date(System.currentTimeMillis() - 2 * Time.HOUR);
return new Date(0);
}
@Override
@@ -15,12 +15,12 @@
*/
package com.intellij.psi.impl.source.javadoc;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiType;
import com.intellij.psi.javadoc.JavadocTagInfo;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.util.ArrayUtil;
/**
@@ -53,7 +53,7 @@ class ReturnDocTagInfo implements JavadocTagInfo {
PsiMethod method = (PsiMethod)element;
final PsiType type = method.getReturnType();
if (type == null) return false;
return type != PsiType.VOID;
return !PsiType.VOID.equals(type);
}
@Override
@@ -1491,7 +1491,7 @@ public class InferenceSession {
final PsiType sReturnType = sSubstitutor.substitute(sInterfaceMethod.getReturnType());
final PsiType tReturnType = tSubstitutor.substitute(tInterfaceMethod.getReturnType());
if (tReturnType == PsiType.VOID) {
if (PsiType.VOID.equals(tReturnType)) {
return true;
}
@@ -1507,8 +1507,8 @@ public class InferenceSession {
return false;
}
} else {
final boolean sPrimitive = sReturnType instanceof PsiPrimitiveType && sReturnType != PsiType.VOID;
final boolean tPrimitive = tReturnType instanceof PsiPrimitiveType && tReturnType != PsiType.VOID;
final boolean sPrimitive = sReturnType instanceof PsiPrimitiveType && !PsiType.VOID.equals(sReturnType);
final boolean tPrimitive = tReturnType instanceof PsiPrimitiveType && !PsiType.VOID.equals(tReturnType);
if (sPrimitive ^ tPrimitive) {
for (PsiExpression returnExpression : returnExpressions) {
if (!PsiPolyExpressionUtil.isPolyExpression(returnExpression)) {
@@ -1557,19 +1557,19 @@ public class InferenceSession {
}
final PsiType sReturnType = sSubstitutor.substitute(sInterfaceMethod.getReturnType());
final PsiType tReturnType = tSubstitutor.substitute(tInterfaceMethod.getReturnType());
if (tReturnType == PsiType.VOID) {
if (PsiType.VOID.equals(tReturnType)) {
return true;
}
final boolean sPrimitive = sReturnType instanceof PsiPrimitiveType && sReturnType != PsiType.VOID;
final boolean tPrimitive = tReturnType instanceof PsiPrimitiveType && tReturnType != PsiType.VOID;
final boolean sPrimitive = sReturnType instanceof PsiPrimitiveType && !PsiType.VOID.equals(sReturnType);
final boolean tPrimitive = tReturnType instanceof PsiPrimitiveType && !PsiType.VOID.equals(tReturnType);
if (sPrimitive ^ tPrimitive) {
final PsiMember member = ((PsiMethodReferenceExpression)arg).getPotentiallyApplicableMember();
LOG.assertTrue(member != null, arg);
if (member instanceof PsiMethod) {
final PsiType methodReturnType = ((PsiMethod)member).getReturnType();
if (sPrimitive && methodReturnType instanceof PsiPrimitiveType && methodReturnType != PsiType.VOID ||
if (sPrimitive && methodReturnType instanceof PsiPrimitiveType && !PsiType.VOID.equals(methodReturnType) ||
tPrimitive && methodReturnType instanceof PsiClassType) {
return true;
}
@@ -85,7 +85,7 @@ public class PsiGraphInferenceHelper implements PsiInferenceHelper {
PsiType arg,
boolean isContraVariantPosition,
LanguageLevel languageLevel) {
if (arg == PsiType.VOID || param == PsiType.VOID) return PsiType.NULL;
if (PsiType.VOID.equals(arg) || PsiType.VOID.equals(param)) return PsiType.NULL;
if (param instanceof PsiArrayType && arg instanceof PsiArrayType) {
return getSubstitutionForTypeParameter(typeParam, ((PsiArrayType)param).getComponentType(), ((PsiArrayType)arg).getComponentType(), isContraVariantPosition, languageLevel);
}
@@ -194,7 +194,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
PsiType returnType,
Set<InferenceVariable> result) {
if (psiExpression instanceof PsiLambdaExpression) {
if (returnType != PsiType.VOID) {
if (!PsiType.VOID.equals(returnType)) {
final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions((PsiLambdaExpression)psiExpression);
for (PsiExpression expression : returnExpressions) {
final Set<InferenceVariable> resultInputVars = createSelfConstraint(returnType, expression).getInputVariables(session);
@@ -104,8 +104,8 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
} else {
return false;
}
if (returnType != PsiType.VOID && returnType != null) {
if (applicableMethodReturnType == PsiType.VOID) {
if (!PsiType.VOID.equals(returnType) && returnType != null) {
if (PsiType.VOID.equals(applicableMethodReturnType)) {
return false;
}
@@ -125,7 +125,7 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
return substitutor;
}
if (includeReturnConstraint && interfaceMethodReturnType != PsiType.VOID && interfaceMethodReturnType != null) {
if (includeReturnConstraint && !PsiType.VOID.equals(interfaceMethodReturnType) && interfaceMethodReturnType != null) {
final PsiType returnType = method.isConstructor() ? composeReturnType(containingClass, substitutor) : method.getReturnType();
if (returnType != null) {
session.registerReturnTypeConstraints(returnType, interfaceMethodReturnType);
@@ -224,7 +224,7 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
}
PsiType methodReturnType = interfaceMethod.getReturnType();
if (methodReturnType != null && methodReturnType != PsiType.VOID) {
if (methodReturnType != null && !PsiType.VOID.equals(methodReturnType)) {
Map<PsiElement, PsiType> map = LambdaUtil.getFunctionalTypeMap();
try {
if (map.put(this, leftType) != null) {
@@ -249,7 +249,7 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
}
final PsiType methodReturnType = interfaceMethod.getReturnType();
final PsiElement body = getBody();
if (methodReturnType == PsiType.VOID) {
if (PsiType.VOID.equals(methodReturnType)) {
if (body instanceof PsiCodeBlock) {
return isVoidCompatible();
} else {
@@ -460,7 +460,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
if (interfaceMethod != null) {
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(left);
if (interfaceReturnType == PsiType.VOID || interfaceReturnType == null) {
if (PsiType.VOID.equals(interfaceReturnType) || interfaceReturnType == null) {
return true;
}
@@ -477,7 +477,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
returnType = ((PsiMethod)resolve).getReturnType();
}
if (returnType == PsiType.VOID) {
if (PsiType.VOID.equals(returnType)) {
return false;
}
+1
View File
@@ -49,5 +49,6 @@
<orderEntry type="module" module-name="jetgroovy" scope="TEST" />
<orderEntry type="module" module-name="lang-tests" scope="TEST" />
<orderEntry type="library" scope="TEST" name="mockito" level="project" />
<orderEntry type="library" scope="TEST" name="assertJ" level="project" />
</component>
</module>
@@ -75,6 +75,16 @@ public class InferredTypeTest extends LightCodeInsightFixtureTestCase {
assertTrue(ensureNotCached.getCanonicalText(), ensureNotCached.equalsToText("java.util.List<java.lang.Integer>"));
}
public void testAnnotatedVoidReturnType() throws Exception {
myFixture.addClass("@java.lang.annotation.Target(value={java.lang.annotation.ElementType.TYPE_USE}) @interface D {}");
final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("R.java", "public interface R {@D void run();}");
final PsiClass psiClass = file.getClasses()[0];
final PsiMethod method = psiClass.getMethods()[0];
assertFalse(PsiType.VOID == method.getReturnType());
myFixture.configureByText("a.java", "class A {{R r = () -> {};}} ");
myFixture.checkHighlighting(false, false, false);
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
@@ -17,11 +17,14 @@ package com.intellij.psi.codeStyle.autodetect;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
public class DetectIndentAndTypeTest extends LightPlatformCodeInsightFixtureTestCase {
private CodeStyleSettings mySettings;
@@ -146,4 +149,25 @@ public class DetectIndentAndTypeTest extends LightPlatformCodeInsightFixtureTest
"\t}\n" +
"}\n");
}
public void testDoNotIndentOptions_WhenTabsDetected_AndUseTabsWasSetByDefault() {
CommonCodeStyleSettings common = mySettings.getCommonSettings(JavaLanguage.INSTANCE);
CommonCodeStyleSettings.IndentOptions indentOptions = common.getIndentOptions();
assert indentOptions != null;
indentOptions.USE_TAB_CHARACTER = true;
indentOptions.TAB_SIZE = 8;
indentOptions.INDENT_SIZE = 4;
indentOptions.CONTINUATION_INDENT_SIZE = 8;
myFixture.configureByText(JavaFileType.INSTANCE, myText);
PsiFile file = myFixture.getFile();
CommonCodeStyleSettings.IndentOptions options = mySettings.getIndentOptionsByFile(file);
assertThat(options.INDENT_SIZE).isEqualTo(4);
assertThat(indentOptions.CONTINUATION_INDENT_SIZE).isEqualTo(8);
}
}
@@ -36,14 +36,31 @@ public class JavaAutoDetectIndentPerformanceTest extends AbstractIndentAutoDetec
@NotNull
@Override
protected String getFileNameWithExtension() {
return getTestName(true) + ".java";
return "bigFile.java";
}
public void testBigFile() {
Ref<IndentOptions> ref = checkPerformanceRelativelyToFileRead();
//to ensure if worked as expected
Assert.assertEquals("Detect indent mismatch", 2, ref.get().INDENT_SIZE);
public void testBigColdFile() {
Ref<IndentOptions> ref = Ref.create();
long fileLoadTime = trackTime(() -> configureByFile(getFileNameWithExtension()));
long detectingTime = trackTime(() -> ref.set(detectIndentOptions()));
double ratio = (double)detectingTime / fileLoadTime;
if (ratio > 0.2) {
TeamCityLogger.error("Detecting indent have taken too much time proportionally to file read time " + ratio);
} else {
String msg = "Detecting indent relatively to file read " + ratio;
TeamCityLogger.info(msg);
System.out.println(msg);
}
//to ensure it worked as expected
Assert.assertEquals("Detect indent mismatch", 2, ref.get().INDENT_SIZE);
}
public void testBigHotFile() {
configureByFile(getFileNameWithExtension());
AbstractIndentAutoDetectionTest.detectIndentOptions();
PlatformTestUtil
.startPerformanceTest("Detecting indent on hot file", 30, AbstractIndentAutoDetectionTest::detectIndentOptions)
.cpuBound()
@@ -55,22 +72,4 @@ public class JavaAutoDetectIndentPerformanceTest extends AbstractIndentAutoDetec
runnable.run();
return System.currentTimeMillis() - startTime;
}
private Ref<IndentOptions> checkPerformanceRelativelyToFileRead() {
Ref<IndentOptions> ref = Ref.create();
long fileLoadTime = trackTime(() -> configureByFile(getFileNameWithExtension()));
long detectingTime = trackTime(() -> ref.set(detectIndentOptions()));
double ratio = (double)detectingTime / fileLoadTime;
if (ratio > 0.2) {
TeamCityLogger.error("Detecting indent have taken too much time proportionally to file read time " + ratio);
} else {
String msg = "Detecting indent relatively to file read " + ratio;
TeamCityLogger.info(msg);
System.out.println(msg);
}
return ref;
}
}
@@ -16,54 +16,94 @@
package com.intellij.testIntergration
import com.intellij.execution.TestStateStorage
import com.intellij.testFramework.UsefulTestCase.*
import com.intellij.execution.testframework.JavaTestLocator
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.testIntegration.RecentTestRunner
import com.intellij.testIntegration.SelectTestStep
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import org.mockito.Matchers
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import java.util.*
class RecentTestsStepTest {
val runner = mock(RecentTestRunner::class.java)
val runner = createRunner()
val passed = TestStateStorage.Record(TestStateInfo.Magnitude.PASSED_INDEX.value, Date())
val failed = TestStateStorage.Record(TestStateInfo.Magnitude.FAILED_INDEX.value, Date())
@Test
fun `suites comes before their children tests`() {
fun `when suite passed - show only suite`() {
val map: MutableMap<String, TestStateStorage.Record> = hashMapOf()
val now = Date()
map.put("java:suite://JavaFormatterSuperDuperTest", TestStateStorage.Record(1, now))
map.put("java:test://Test.textXXX", TestStateStorage.Record(1, now))
map.put("java:suite://Test", TestStateStorage.Record(1, now))
map.put("java:test://Test.textYYY", TestStateStorage.Record(1, now))
map.put("java:test://Test.textZZZ", TestStateStorage.Record(1, now))
map.put("java:test://JavaFormatterSuperDuperTest.testItMakesMeSadToFixIt", TestStateStorage.Record(1, now))
map.put("java:test://Test.textQQQ", TestStateStorage.Record(1, now))
map.put("java:test://JavaFormatterSuperDuperTest.testUnconditionalAlignmentErrorneous", TestStateStorage.Record(1, now))
map.put("java:suite://JavaFormatterSuperDuperTest", passed)
map.put("java:test://Test.textXXX", passed)
map.put("java:suite://Test", passed)
map.put("java:test://Test.textYYY", passed)
map.put("java:test://Test.textZZZ", passed)
map.put("java:test://JavaFormatterSuperDuperTest.testItMakesMeSadToFixIt", passed)
map.put("java:test://Test.textQQQ", passed)
map.put("java:test://JavaFormatterSuperDuperTest.testUnconditionalAlignmentErrorneous", passed)
val step = SelectTestStep(map, runner)
val expected = listOf(
"java:suite://JavaFormatterSuperDuperTest",
"java:test://JavaFormatterSuperDuperTest.testItMakesMeSadToFixIt",
"java:test://JavaFormatterSuperDuperTest.testUnconditionalAlignmentErrorneous",
"java:suite://Test",
"java:test://Test.textQQQ",
"java:test://Test.textXXX",
"java:test://Test.textYYY",
"java:test://Test.textZZZ"
"java:suite://Test"
)
assertContainsOrdered(step.values, expected)
assertSize(8, step.values)
assertThat(step.values).isEqualTo(expected)
}
@Test
fun `show failed first`() {
val map: MutableMap<String, TestStateStorage.Record> = hashMapOf()
map.put("java:suite://JavaFormatterSuperDuperTest", failed)
map.put("java:test://Test.textXXX", passed)
map.put("java:suite://Test", passed)
map.put("java:suite://JavaFormatterFailed", failed)
map.put("java:test://JavaFormatterFailed.fail", failed)
map.put("java:test://Test.textYYY", passed)
map.put("java:test://Test.textZZZ", passed)
map.put("java:test://JavaFormatterSuperDuperTest.testFail", failed)
map.put("java:test://Test.textQQQ", passed)
map.put("java:test://JavaFormatterSuperDuperTest.testUnconditionalAlignmentErrorneous", passed)
val step = SelectTestStep(map, runner)
val expected = listOf(
"java:suite://JavaFormatterFailed",
"java:test://JavaFormatterFailed.fail",
"java:suite://JavaFormatterSuperDuperTest",
"java:test://JavaFormatterSuperDuperTest.testFail",
"java:suite://Test"
)
assertThat(step.values).isEqualTo(expected)
}
private fun createRunner(): RecentTestRunner {
val runner = mock(RecentTestRunner::class.java)
`when`(runner.isSuite(Matchers.anyString())).thenAnswer {
val url = it.arguments[0] as String
val protocol = VirtualFileManager.extractProtocol(url)
JavaTestLocator.SUITE_PROTOCOL.startsWith(protocol.toString())
}
return runner
}
@Test
fun `shown value without protocol`() {
val step = SelectTestStep(emptyMap(), runner)
var shownValue = step.getTextFor("java:suite://JavaFormatterSuperDuperTest")
assertEquals(shownValue, "JavaFormatterSuperDuperTest")
assertThat(shownValue).isEqualTo("JavaFormatterSuperDuperTest")
shownValue = step.getTextFor("java:test://JavaFormatterSuperDuperTest.testItMakesMeSadToFixIt")
assertEquals(shownValue, "JavaFormatterSuperDuperTest.testItMakesMeSadToFixIt")
assertThat(shownValue).isEqualTo("JavaFormatterSuperDuperTest.testItMakesMeSadToFixIt")
}
}
@@ -19,10 +19,12 @@ package com.intellij.lang;
import com.intellij.lexer.Lexer;
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.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.LanguageSubstitutors;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.templateLanguages.TemplateLanguage;
@@ -47,6 +49,13 @@ public final class LanguageUtil {
};
@Nullable
public static Language getLanguageForPsi(@NotNull Project project, @Nullable VirtualFile file) {
Language language = getFileLanguage(file);
if (language == null) return null;
return LanguageSubstitutors.INSTANCE.substituteLanguage(language, file, project);
}
@Nullable
public static Language getFileLanguage(@Nullable VirtualFile file) {
return file == null ? null : getFileTypeLanguage(file.getFileType());
@@ -19,6 +19,7 @@ import com.google.common.util.concurrent.Atomics;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.LanguageUtil;
import com.intellij.lang.ParserDefinition;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.undo.UndoConstants;
@@ -28,7 +29,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.fileTypes.PlainTextLanguage;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
@@ -134,11 +134,9 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi
if (fileType.isBinary()) return Language.ANY;
if (isTooLargeForIntelligence(file)) return PlainTextLanguage.INSTANCE;
if (fileType instanceof LanguageFileType) {
return LanguageSubstitutors.INSTANCE.substituteLanguage(((LanguageFileType)fileType).getLanguage(), file, project);
}
Language language = LanguageUtil.getLanguageForPsi(project, file);
return PlainTextLanguage.INSTANCE;
return language != null ? language : PlainTextLanguage.INSTANCE;
}
@Override
@@ -17,6 +17,7 @@ package com.intellij.ide.scratch;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageUtil;
import com.intellij.lang.PerFileMappings;
import com.intellij.lang.StdLanguages;
import com.intellij.lang.injection.InjectedLanguageManager;
@@ -196,7 +197,7 @@ public class ScratchFileActions {
@Override
public Language fun(VirtualFile file) {
Language lang = fileService.getScratchesMapping().getMapping(file);
return lang != null ? lang : ScratchUtil.getLanguage(project, file);
return lang != null ? lang : LanguageUtil.getLanguageForPsi(project, file);
}
};
}
@@ -224,7 +224,7 @@ public class ScratchFileServiceImpl extends ScratchFileService implements Persis
public SyntaxHighlighter create(@NotNull FileType fileType, @Nullable Project project, @Nullable VirtualFile file) {
if (project == null || file == null || !(fileType instanceof ScratchFileType)) return null;
Language language = ScratchUtil.getLanguage(project, file);
Language language = LanguageUtil.getLanguageForPsi(project, file);
return language == null ? null : SyntaxHighlighterFactory.getSyntaxHighlighter(language, project, file);
}
}
@@ -15,12 +15,7 @@
*/
package com.intellij.ide.scratch;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.LanguageSubstitutors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -38,11 +33,4 @@ public class ScratchUtil {
public static boolean isScratch(@Nullable VirtualFile file) {
return file != null && file.getFileType() == ScratchFileType.INSTANCE;
}
@Nullable
public static Language getLanguage(@NotNull Project project, @Nullable VirtualFile file) {
Language language = LanguageUtil.getFileLanguage(file);
if (language == null) return null;
return LanguageSubstitutors.INSTANCE.substituteLanguage(language, file, project);
}
}
@@ -75,16 +75,11 @@ public class IndentOptionsDetectorImpl implements IndentOptionsDetector {
private void adjustIndentOptions(@NotNull IndentOptions indentOptions, @NotNull IndentUsageStatistics stats) {
if (isTabsUsed(stats)) {
setUseTabs(indentOptions, true);
int continuationRatio = indentOptions.INDENT_SIZE == 0 ? 1
: indentOptions.CONTINUATION_INDENT_SIZE / indentOptions.INDENT_SIZE;
indentOptions.INDENT_SIZE = indentOptions.TAB_SIZE;
indentOptions.CONTINUATION_INDENT_SIZE = indentOptions.TAB_SIZE * continuationRatio;
adjustForTabUsage(indentOptions);
}
else if (isSpacesUsed(stats)) {
setUseTabs(indentOptions, false);
indentOptions.USE_TAB_CHARACTER = false;
int newIndentSize = getPositiveIndentSize(stats);
if (newIndentSize > 0) {
if (indentOptions.INDENT_SIZE != newIndentSize) {
@@ -105,11 +100,16 @@ public class IndentOptionsDetectorImpl implements IndentOptionsDetector {
return stats.getTotalLinesWithLeadingTabs() > stats.getTotalLinesWithLeadingSpaces();
}
private void setUseTabs(@NotNull IndentOptions indentOptions, boolean useTabs) {
if (indentOptions.USE_TAB_CHARACTER != useTabs) {
indentOptions.USE_TAB_CHARACTER = useTabs;
LOG.debug("Tab usage set to " + useTabs + " for file " + myFile);
}
private void adjustForTabUsage(@NotNull IndentOptions indentOptions) {
if (indentOptions.USE_TAB_CHARACTER) return;
int continuationRatio = indentOptions.INDENT_SIZE == 0 ? 1 : indentOptions.CONTINUATION_INDENT_SIZE / indentOptions.INDENT_SIZE;
indentOptions.USE_TAB_CHARACTER = true;
indentOptions.INDENT_SIZE = indentOptions.TAB_SIZE;
indentOptions.CONTINUATION_INDENT_SIZE = indentOptions.TAB_SIZE * continuationRatio;
LOG.debug("Using tabs for: " + myFile);
}
private static int getPositiveIndentSize(@NotNull IndentUsageStatistics stats) {
@@ -1,76 +0,0 @@
package org.jetbrains.debugger;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.concurrency.Promise;
import org.jetbrains.debugger.values.Value;
import org.jetbrains.io.JsonUtil;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
public final class ValueModifierUtil {
private static final Pattern KEY_NOTATION_PROPERTY_NAME_PATTERN = Pattern.compile("[\\p{L}_$]+[\\d\\p{L}_$]*");
@NotNull
public static Promise<Void> setValue(@NotNull final Variable variable, String newValue, @NotNull final EvaluateContext evaluateContext, @NotNull final ValueModifier modifier) {
return evaluateContext.evaluate(newValue).then(new Function<EvaluateResult, Void>() {
@Override
public Void fun(EvaluateResult result) {
modifier.setValue(variable, result.value, evaluateContext);
return null;
}
});
}
@NotNull
public static Promise<Value> evaluateGet(@NotNull final Variable variable,
@NotNull Object host,
@NotNull EvaluateContext evaluateContext,
@NotNull String selfName) {
StringBuilder builder = new StringBuilder(selfName);
appendUnquotedName(builder, variable.getName());
return evaluateContext.evaluate(builder.toString(), Collections.singletonMap(selfName, host), false)
.then(new Function<EvaluateResult, Value>() {
@Override
public Value fun(EvaluateResult result) {
variable.setValue(result.value);
return result.value;
}
});
}
@NotNull
public static String propertyNamesToString(@NotNull List<String> list, boolean quotedAware) {
StringBuilder builder = new StringBuilder();
for (int i = list.size() - 1; i >= 0; i--) {
String name = list.get(i);
doAppendName(builder, name, quotedAware && (name.charAt(0) == '"' || name.charAt(0) == '\''));
}
return builder.toString();
}
public static void appendUnquotedName(@NotNull StringBuilder builder, @NotNull String name) {
doAppendName(builder, name, false);
}
private static void doAppendName(@NotNull StringBuilder builder, @NotNull String name, boolean quoted) {
boolean useKeyNotation = !quoted && KEY_NOTATION_PROPERTY_NAME_PATTERN.matcher(name).matches();
if (builder.length() != 0) {
builder.append(useKeyNotation ? '.' : '[');
}
if (useKeyNotation) {
builder.append(name);
}
else {
if (quoted) {
builder.append(name);
}
else {
JsonUtil.escape(name, builder);
}
builder.append(']');
}
}
}
@@ -0,0 +1,65 @@
package org.jetbrains.debugger
import com.intellij.util.Function
import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.thenAsyncAccept
import org.jetbrains.debugger.values.Value
import org.jetbrains.io.JsonUtil
import java.util.*
import java.util.regex.Pattern
private val KEY_NOTATION_PROPERTY_NAME_PATTERN = Pattern.compile("[\\p{L}_$]+[\\d\\p{L}_$]*")
object ValueModifierUtil {
fun setValue(variable: Variable,
newValue: String,
evaluateContext: EvaluateContext,
modifier: ValueModifier) = evaluateContext.evaluate(newValue)
.thenAsyncAccept { modifier.setValue(variable, it.value, evaluateContext) }
fun evaluateGet(variable: Variable,
host: Any,
evaluateContext: EvaluateContext,
selfName: String): Promise<Value> {
val builder = StringBuilder(selfName)
appendUnquotedName(builder, variable.name)
return evaluateContext.evaluate(builder.toString(), Collections.singletonMap(selfName, host), false).then(object : Function<EvaluateResult, Value> {
override fun `fun`(result: EvaluateResult): Value {
variable.value = result.value
return result.value
}
})
}
fun propertyNamesToString(list: List<String>, quotedAware: Boolean): String {
val builder = StringBuilder()
for (i in list.indices.reversed()) {
val name = list[i]
doAppendName(builder, name, quotedAware && (name[0] == '"' || name[0] == '\''))
}
return builder.toString()
}
fun appendUnquotedName(builder: StringBuilder, name: String) {
doAppendName(builder, name, false)
}
}
private fun doAppendName(builder: StringBuilder, name: String, quoted: Boolean) {
val useKeyNotation = !quoted && KEY_NOTATION_PROPERTY_NAME_PATTERN.matcher(name).matches()
if (builder.length != 0) {
builder.append(if (useKeyNotation) '.' else '[')
}
if (useKeyNotation) {
builder.append(name)
}
else {
if (quoted) {
builder.append(name)
}
else {
JsonUtil.escape(name, builder)
}
builder.append(']')
}
}
@@ -1,14 +0,0 @@
package org.jetbrains.debugger.values;
import org.jetbrains.concurrency.Promise;
public interface StringValue extends Value {
boolean isTruncated();
int getLength();
/**
* Asynchronously reloads object value with extended size limit
*/
Promise<String> getFullString();
}
@@ -0,0 +1,14 @@
package org.jetbrains.debugger.values
import org.jetbrains.concurrency.Promise
interface StringValue : Value {
val isTruncated: Boolean
val length: Int
/**
* Asynchronously reloads object value with extended size limit
*/
val fullString: Promise<String>
}
@@ -27,8 +27,11 @@ import org.jetbrains.debugger.*
class CallFrameView @JvmOverloads constructor(val callFrame: CallFrame,
private val viewSupport: DebuggerViewSupport,
val script: Script? = null,
private val sourceInfo: SourceInfo? = viewSupport.getSourceInfo(script, callFrame),
private val isInLibraryContent: Boolean = sourceInfo != null && viewSupport.isInLibraryContent(sourceInfo, script)) : XStackFrame(), VariableContext {
sourceInfo: SourceInfo? = null,
isInLibraryContent: Boolean? = null) : XStackFrame(), VariableContext {
private val sourceInfo = sourceInfo ?: viewSupport.getSourceInfo(script, callFrame)
private val isInLibraryContent: Boolean = isInLibraryContent ?: (this.sourceInfo != null && viewSupport.isInLibraryContent(this.sourceInfo, script))
private var evaluator: XDebuggerEvaluator? = null
override fun getEqualityObject() = callFrame.equalityObject
@@ -18,19 +18,16 @@ package org.jetbrains.debugger.frame
import com.intellij.xdebugger.frame.XExecutionStack
import com.intellij.xdebugger.frame.XStackFrame
import com.intellij.xdebugger.settings.XDebuggerSettingsManager
import org.jetbrains.debugger.DebuggerViewSupport
import org.jetbrains.debugger.Script
import org.jetbrains.debugger.SuspendContext
import org.jetbrains.debugger.done
import org.jetbrains.debugger.*
import java.util.*
internal class ExecutionStackImpl(private val suspendContext: SuspendContext, private val viewSupport: DebuggerViewSupport, private val topFrameScript: Script?) : XExecutionStack("") {
internal class ExecutionStackImpl(private val suspendContext: SuspendContext, private val viewSupport: DebuggerViewSupport, private val topFrameScript: Script?, private val topFrameSourceInfo: SourceInfo? = null) : XExecutionStack("") {
private var topCallFrameView: CallFrameView? = null
override fun getTopFrame(): CallFrameView? {
val topCallFrame = suspendContext.topFrame
if (topCallFrameView == null || topCallFrameView!!.callFrame != topCallFrame) {
topCallFrameView = if (topCallFrame == null) null else CallFrameView(topCallFrame, viewSupport, topFrameScript)
topCallFrameView = if (topCallFrame == null) null else CallFrameView(topCallFrame, viewSupport, topFrameScript, topFrameSourceInfo)
}
return topCallFrameView
}
@@ -1,65 +0,0 @@
package org.jetbrains.debugger.frame;
import com.intellij.xdebugger.frame.XExecutionStack;
import com.intellij.xdebugger.frame.XSuspendContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.concurrency.AsyncFunction;
import org.jetbrains.concurrency.Promise;
import org.jetbrains.debugger.*;
import org.jetbrains.debugger.values.StringValue;
import org.jetbrains.debugger.values.Value;
public class SuspendContextImpl extends XSuspendContext {
private final ExecutionStackImpl executionStack;
private final SuspendContext suspendContext;
protected SuspendContextImpl(@NotNull SuspendContext suspendContext, @NotNull DebuggerViewSupport debugProcess, @Nullable Script topFrameScript) {
executionStack = new ExecutionStackImpl(suspendContext, debugProcess, topFrameScript);
this.suspendContext = suspendContext;
}
@SuppressWarnings("UnusedDeclaration")
public void clearObjectCaches() {
suspendContext.getValueManager().clearCaches();
}
@Override
@NotNull
public XExecutionStack getActiveExecutionStack() {
return executionStack;
}
@NotNull
public Promise<String> evaluateExpression(@NotNull String expression) {
CallFrameView frame = executionStack.getTopFrame();
if (frame == null) {
return Promise.reject("Top frame is null");
}
else {
return evaluateExpression(frame.getCallFrame().getEvaluateContext(), expression);
}
}
@NotNull
private static Promise<String> evaluateExpression(@NotNull EvaluateContext evaluateContext, @NotNull String expression) {
return evaluateContext.evaluate(expression).then(new AsyncFunction<EvaluateResult, String>() {
@NotNull
@Override
public Promise<String> fun(EvaluateResult result) {
Value value = result.value;
if (value == null) {
return Promise.resolve("Log expression result doesn't have value");
}
else {
if (value instanceof StringValue && ((StringValue)value).isTruncated()) {
return ((StringValue)value).getFullString();
}
else {
return Promise.resolve(value.getValueString());
}
}
}
});
}
}
@@ -0,0 +1,46 @@
/*
* 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 org.jetbrains.debugger.frame
import com.intellij.xdebugger.frame.XSuspendContext
import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.rejectedPromise
import org.jetbrains.concurrency.resolvedPromise
import org.jetbrains.concurrency.thenAsync
import org.jetbrains.debugger.*
import org.jetbrains.debugger.values.StringValue
open class SuspendContextImpl(suspendContext: SuspendContext, debugProcess: DebuggerViewSupport, topFrameScript: Script?, topFrameSourceInfo: SourceInfo? = null) : XSuspendContext() {
private val executionStack = ExecutionStackImpl(suspendContext, debugProcess, topFrameScript, topFrameSourceInfo)
override fun getActiveExecutionStack() = executionStack
fun evaluateExpression(expression: String): Promise<String> {
val frame = executionStack.topFrame ?: return rejectedPromise("Top frame is null")
return evaluateExpression(frame.callFrame.evaluateContext, expression)
}
private fun evaluateExpression(evaluateContext: EvaluateContext, expression: String) = evaluateContext.evaluate(expression)
.thenAsync {
val value = it.value ?: return@thenAsync resolvedPromise("Log expression result doesn't have value")
if (value is StringValue && value.isTruncated) {
value.fullString
}
else {
resolvedPromise(value.valueString!!)
}
}
}
@@ -4,9 +4,7 @@ import com.intellij.dupLocator.iterators.ArrayBackedNodeIterator;
import com.intellij.dupLocator.iterators.NodeIterator;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.fileTypes.LanguageFileType;
@@ -38,7 +36,10 @@ import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.SoftReference;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* This class makes program structure tree matching:
@@ -47,6 +48,7 @@ public class MatcherImpl {
private static final Logger LOG = Logger.getInstance("#com.intellij.structuralsearch.impl.matcher.MatcherImpl");
// project being worked on
private final Project project;
private final PsiDocumentManager documentManager;
// context of matching
private final MatchContext matchContext;
@@ -69,6 +71,7 @@ public class MatcherImpl {
matchContext.setOptions(matchOptions);
cacheCompiledPattern(matchOptions, PatternCompiler.compilePattern(project,matchOptions));
}
documentManager = PsiDocumentManager.getInstance(this.project);
}
static class LastMatchData {
@@ -534,23 +537,6 @@ public class MatcherImpl {
if (files.size() == 0) return;
final Runnable action = new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
if (project.isDisposed()) return;
final PsiFile psiFile = files.get(0).getContainingFile();
final PsiDocumentManager manager = PsiDocumentManager.getInstance(project);
final Document document = manager.getDocument(psiFile);
if (document != null) manager.commitDocument(document);
}
});
}
};
ApplicationManager.getApplication().invokeAndWait(action, ModalityState.defaultModalityState());
if (project.isDisposed()) return;
final LanguageFileType fileType = (LanguageFileType)matchContext.getOptions().getFileType();
final Language patternLanguage = fileType.getLanguage();
for (PsiElement file : files) {
@@ -559,8 +545,7 @@ public class MatcherImpl {
}
final PsiElement finalFile = file;
ApplicationManager.getApplication().runReadAction(
new Runnable() {
documentManager.commitAndRunReadAction(new Runnable() {
public void run() {
PsiElement file = finalFile;
if (!file.isValid()) return;
@@ -120,7 +120,7 @@ public class MavenDependencyCompletionAndResolutionTest extends MavenDomWithIndi
" </dependency>" +
"</dependencies>");
assertCompletionVariants(myProjectPom);
assertCompletionVariants(myProjectPom, "RELEASE", "LATEST");
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
@@ -134,7 +134,7 @@ public class MavenDependencyCompletionAndResolutionTest extends MavenDomWithIndi
" </dependency>" +
"</dependencies>");
assertCompletionVariants(myProjectPom);
assertCompletionVariants(myProjectPom, "RELEASE", "LATEST");
}
public void testDoNotCompleteVersionIfNoGroupIdAndArtifactId() throws Exception {
@@ -16,6 +16,7 @@
package com.jetbrains.python.debugger;
import com.intellij.ide.scratch.ScratchUtil;
import com.intellij.lang.LanguageUtil;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
@@ -70,7 +71,7 @@ public class PyLineBreakpointType extends XLineBreakpointTypeBase {
}
private static boolean isPythonScratch(@NotNull Project project, @NotNull VirtualFile file) {
return ScratchUtil.isScratch(file) && ScratchUtil.getLanguage(project, file) == PythonLanguage.INSTANCE;
return ScratchUtil.isScratch(file) && LanguageUtil.getLanguageForPsi(project, file) == PythonLanguage.INSTANCE;
}
private static boolean notStoppableElementType(IElementType elementType) {
@@ -39,7 +39,7 @@ public class CustomDomChildrenDescriptionImpl extends AbstractDomChildDescriptio
public CustomDomChildrenDescriptionImpl(@NotNull final JavaMethod getter) {
this(getter, DomReflectionUtil.extractCollectionElementType(getter.getGenericReturnType()),
TagNameDescriptor.EMPTY, TagNameDescriptor.EMPTY);
AttributeDescriptor.EMPTY, AttributeDescriptor.EMPTY);
}
public CustomDomChildrenDescriptionImpl(DomExtensionImpl custom) {
@@ -49,7 +49,7 @@ public class DomExtensionImpl implements DomExtension {
private boolean mySoft;
private int myCount = 1;
private Map myUserMap;
private CustomDomChildrenDescription.TagNameDescriptor myTagNameDescriptor = CustomDomChildrenDescription.TagNameDescriptor.EMPTY;
private CustomDomChildrenDescription.TagNameDescriptor myTagNameDescriptor = CustomDomChildrenDescription.AttributeDescriptor.EMPTY;
private CustomDomChildrenDescription.AttributeDescriptor myAttributesDescriptor;
public DomExtensionImpl(final Type type, final XmlName xmlName) {
@@ -88,7 +88,7 @@ public class DomExtensionsRegistrarImpl implements DomExtensionsRegistrar {
@Override
@NotNull
public DomExtension registerCustomChildrenExtension(@NotNull final Type type) {
return registerCustomChildrenExtension(type, CustomDomChildrenDescription.TagNameDescriptor.EMPTY);
return registerCustomChildrenExtension(type, CustomDomChildrenDescription.AttributeDescriptor.EMPTY);
}
@NotNull
@@ -38,8 +38,6 @@ public interface CustomDomChildrenDescription extends AbstractDomChildrenDescrip
class TagNameDescriptor {
public static final AttributeDescriptor EMPTY = new AttributeDescriptor();
public Set<EvaluatedXmlName> getCompletionVariants(@NotNull DomElement parent) {
return Collections.emptySet();
}
@@ -57,6 +55,7 @@ public interface CustomDomChildrenDescription extends AbstractDomChildrenDescrip
}
class AttributeDescriptor extends TagNameDescriptor {
public static final AttributeDescriptor EMPTY = new AttributeDescriptor();
public Type getElementType(DomElement child) {
throw new UnsupportedOperationException();