mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# The file might be automatically updated. Comments and empty lines will be removed.
|
||||
kotlinPluginBuild=1.1.2-release-IJ2017.2-5
|
||||
kotlinPluginBuild=1.1.3-eap-85-IJ2017.2-1:EAP-1.1
|
||||
jetSignBuild=42.30
|
||||
jdkBuild=u152b927.2
|
||||
|
||||
@@ -95,6 +95,7 @@ public class JUnitUtil {
|
||||
@NonNls public static final String PARAMETERIZED_CLASS_NAME = "org.junit.runners.Parameterized";
|
||||
@NonNls public static final String SUITE_CLASS_NAME = "org.junit.runners.Suite";
|
||||
public static final String JUNIT5_NESTED = "org.junit.jupiter.api.Nested";
|
||||
private static final String HIERARCHICAL_RUNNER = "de.bechte.junit.runners.context.HierarchicalContextRunner";
|
||||
|
||||
public static boolean isSuiteMethod(@NotNull PsiMethod psiMethod) {
|
||||
if (!psiMethod.hasModifierProperty(PsiModifier.PUBLIC)) return false;
|
||||
@@ -213,7 +214,12 @@ public class JUnitUtil {
|
||||
final PsiModifierList modifierList = psiClass.getModifierList();
|
||||
if (modifierList == null) return false;
|
||||
final PsiClass topLevelClass = PsiTreeUtil.getTopmostParentOfType(modifierList, PsiClass.class);
|
||||
if (topLevelClass != null && AnnotationUtil.isAnnotated(topLevelClass, RUN_WITH, true)) return true;
|
||||
if (topLevelClass != null) {
|
||||
PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy(topLevelClass, Collections.singleton(RUN_WITH));
|
||||
if (annotation != null && (topLevelClass == psiClass || isSpecifiedRunner(annotation, HIERARCHICAL_RUNNER))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PsiClassUtil.isRunnableClass(psiClass, true, checkAbstract)) return false;
|
||||
|
||||
@@ -392,11 +398,16 @@ public class JUnitUtil {
|
||||
}
|
||||
|
||||
public static boolean isParameterized(PsiAnnotation annotation) {
|
||||
return isSpecifiedRunner(annotation, "org.junit.runners.Parameterized");
|
||||
}
|
||||
|
||||
private static boolean isSpecifiedRunner(PsiAnnotation annotation,
|
||||
String runnerQName) {
|
||||
final PsiAnnotationMemberValue value = annotation.findAttributeValue(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
|
||||
if (value instanceof PsiClassObjectAccessExpression) {
|
||||
final PsiTypeElement operand = ((PsiClassObjectAccessExpression)value).getOperand();
|
||||
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(operand.getType());
|
||||
return psiClass != null && "org.junit.runners.Parameterized".equals(psiClass.getQualifiedName());
|
||||
return psiClass != null && runnerQName.equals(psiClass.getQualifiedName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ public class JavaDependencyVisitorFactory extends DependencyVisitorFactory {
|
||||
return new MyVisitor(processor, options);
|
||||
}
|
||||
|
||||
private static class MyVisitor extends JavaRecursiveElementWalkingVisitor {
|
||||
private static class MyVisitor extends JavaRecursiveElementVisitor {
|
||||
private final DependenciesBuilder.DependencyProcessor myProcessor;
|
||||
private final VisitorOptions myOptions;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.psi.formatter.java;
|
||||
|
||||
import com.intellij.formatting.*;
|
||||
import com.intellij.formatting.alignment.AlignmentStrategy;
|
||||
import com.intellij.formatting.blocks.CStyleCommentBlock;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -204,6 +205,9 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
return new CommentWithInjectionBlock(child, wrap, alignment, indent, settings, javaSettings);
|
||||
}
|
||||
if (child instanceof LeafElement || childPsi instanceof PsiJavaModuleReferenceElement) {
|
||||
if (child.getElementType() == JavaTokenType.C_STYLE_COMMENT) {
|
||||
return new CStyleCommentBlock(child, indent);
|
||||
}
|
||||
final LeafBlock block = new LeafBlock(child, wrap, alignment, actualIndent);
|
||||
block.setStartOffset(startOffset);
|
||||
return block;
|
||||
@@ -355,7 +359,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
@Nullable
|
||||
@Override
|
||||
public Spacing getSpacing(Block child1, @NotNull Block child2) {
|
||||
return JavaSpacePropertyProcessor.getSpacing(getTreeNode(child2), mySettings, myJavaSettings);
|
||||
return JavaSpacePropertyProcessor.getSpacing(child2, mySettings, myJavaSettings);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1126,12 +1130,15 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static ASTNode getTreeNode(final Block child2) {
|
||||
if (child2 instanceof JavaBlock) {
|
||||
return ((JavaBlock)child2).getFirstTreeNode();
|
||||
protected static ASTNode getTreeNode(final Block block) {
|
||||
if (block instanceof JavaBlock) {
|
||||
return ((JavaBlock)block).getFirstTreeNode();
|
||||
}
|
||||
if (child2 instanceof LeafBlock) {
|
||||
return ((LeafBlock)child2).getTreeNode();
|
||||
if (block instanceof LeafBlock) {
|
||||
return ((LeafBlock)block).getTreeNode();
|
||||
}
|
||||
if (block instanceof CStyleCommentBlock) {
|
||||
return ((CStyleCommentBlock)block).getNode();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
*/
|
||||
package com.intellij.psi.formatter.java;
|
||||
|
||||
import com.intellij.formatting.Block;
|
||||
import com.intellij.formatting.Spacing;
|
||||
import com.intellij.formatting.blocks.CStyleCommentBlock;
|
||||
import com.intellij.formatting.blocks.TextLineBlock;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.lang.java.JavaParserDefinition;
|
||||
@@ -76,7 +79,8 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
|
||||
|
||||
private static final ThreadLocal<JavaSpacePropertyProcessor> mySharedProcessorAllocator = new ThreadLocal<>();
|
||||
|
||||
private void doInit(ASTNode child, CommonCodeStyleSettings settings, JavaCodeStyleSettings javaSettings) {
|
||||
private void doInit(Block block, CommonCodeStyleSettings settings, JavaCodeStyleSettings javaSettings) {
|
||||
ASTNode child = AbstractJavaBlock.getTreeNode(block);
|
||||
if (isErrorElement(child)) {
|
||||
myResult = Spacing.getReadOnlySpacing();
|
||||
return;
|
||||
@@ -101,11 +105,17 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
|
||||
return;
|
||||
}
|
||||
|
||||
if (block instanceof TextLineBlock) {
|
||||
myResult = ((TextLineBlock)block).getSpacing();
|
||||
return;
|
||||
}
|
||||
if (block instanceof CStyleCommentBlock) {
|
||||
myResult = ((CStyleCommentBlock)block).getSpacing();
|
||||
return;
|
||||
}
|
||||
|
||||
if (myChild2 != null && StdTokenSets.COMMENT_BIT_SET.contains(myChild2.getElementType())) {
|
||||
if (myChild2.getElementType() == JavaTokenType.C_STYLE_COMMENT) {
|
||||
myResult = Spacing.getReadOnlySpacing();
|
||||
}
|
||||
else if (mySettings.KEEP_FIRST_COLUMN_COMMENT) {
|
||||
if (mySettings.KEEP_FIRST_COLUMN_COMMENT) {
|
||||
myResult = Spacing.createKeepingFirstColumnSpacing(0, Integer.MAX_VALUE, true, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
else {
|
||||
@@ -1758,7 +1768,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
|
||||
}
|
||||
|
||||
@SuppressWarnings({"ConstantConditions"})
|
||||
public static Spacing getSpacing(ASTNode node, CommonCodeStyleSettings settings, JavaCodeStyleSettings javaSettings) {
|
||||
public static Spacing getSpacing(Block node, CommonCodeStyleSettings settings, JavaCodeStyleSettings javaSettings) {
|
||||
JavaSpacePropertyProcessor spacePropertyProcessor = mySharedProcessorAllocator.get();
|
||||
try {
|
||||
if (spacePropertyProcessor == null) {
|
||||
|
||||
@@ -95,7 +95,7 @@ public class SyntheticCodeBlock implements Block, JavaBlock{
|
||||
|
||||
@Override
|
||||
public Spacing getSpacing(Block child1, @NotNull Block child2) {
|
||||
return JavaSpacePropertyProcessor.getSpacing(AbstractJavaBlock.getTreeNode(child2), mySettings, myJavaSettings);
|
||||
return JavaSpacePropertyProcessor.getSpacing(child2, mySettings, myJavaSettings);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
||||
@@ -172,10 +172,6 @@ public abstract class JavaTestFramework implements TestFramework {
|
||||
return isTestMethod(element, true);
|
||||
}
|
||||
|
||||
public boolean isTestMethod(PsiElement element, boolean checkAbstract) {
|
||||
return isTestMethod(element);
|
||||
}
|
||||
|
||||
public boolean isMyConfigurationType(ConfigurationType type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ public class Main {
|
||||
BinaryOperator<Integer> min = Math::min;
|
||||
String foo = "xyz";
|
||||
|
||||
/*check*/
|
||||
/*check*/
|
||||
boolean b = selector.andThen(Collections.singleton(/* "xyz" here */ "xyz")::contains).apply(/* foo here */ foo);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<CharSequence> list) {
|
||||
/*before dot*/
|
||||
/*after dot*/
|
||||
/*before dot*/
|
||||
/*after dot*/
|
||||
list.stream()
|
||||
/*before dot2*/./*after dot2*/map(cs -> /*length!!!*/ cs.subSequence(/*subsequence*/1, 5).length()).forEach(System.out::println);
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static void test(List<CharSequence> list) {
|
||||
/*out of body*/
|
||||
/*out of body*/
|
||||
list.stream().map(cs -> cs/*in body*/.subSequence(1, 5).length()).forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -2,10 +2,10 @@
|
||||
|
||||
import java.util.stream.Stream;
|
||||
class Test {
|
||||
void foo(Stream<String> stringStream ) {
|
||||
stringStream.filter(name -> name.startsWith("A") && name.//comment2
|
||||
length() > 1//comment
|
||||
/*comment1*/
|
||||
).findAny();
|
||||
}
|
||||
void foo(Stream<String> stringStream ) {
|
||||
stringStream.filter(name -> name.startsWith("A") && name.//comment2
|
||||
length() > 1//comment
|
||||
/*comment1*/
|
||||
).findAny();
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -2,9 +2,9 @@
|
||||
|
||||
import java.util.stream.Stream;
|
||||
class Test {
|
||||
void foo(Stream<String> stringStream ) {
|
||||
stringStream.filt<caret>er(name -> name.startsWith("A"))//comment
|
||||
.filter(a -> a.//comment2
|
||||
length() > 1 /*comment1*/).findAny();
|
||||
}
|
||||
void foo(Stream<String> stringStream ) {
|
||||
stringStream.filt<caret>er(name -> name.startsWith("A"))//comment
|
||||
.filter(a -> a.//comment2
|
||||
length() > 1 /*comment1*/).findAny();
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -11,10 +11,10 @@ public class Main {
|
||||
}
|
||||
|
||||
public Number testOptionalComments(Optional<MyList> strList) {
|
||||
/* optional is present */
|
||||
/*return something */
|
||||
/* optional is absent */
|
||||
/* return null*/
|
||||
/* optional is present */
|
||||
/*return something */
|
||||
/* optional is absent */
|
||||
/* return null*/
|
||||
return strList.map(myList -> myList.size() > /*too big*/ 1 ? myList.get(1) : 1.0).orElse(null);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -8,11 +8,11 @@ class T {
|
||||
}
|
||||
else if (s.startsWith("@")) {
|
||||
return s.substring(1); // return comment
|
||||
/* inline 1 *//* inline 2 */
|
||||
/* inline 1 *//* inline 2 */
|
||||
}
|
||||
else if (s.startsWith("#")) {
|
||||
return "#"; // return comment
|
||||
/* inline */
|
||||
/* inline */
|
||||
}
|
||||
return s; // return comment
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public class Main {
|
||||
}
|
||||
|
||||
public static List<String> testUseName() {
|
||||
/*limit*/
|
||||
/*limit*/
|
||||
List<String> list = new ArrayList<>();
|
||||
long limit = 20;
|
||||
for (String x = ""; ; x = x /* add "a" */ + "a") {
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ public class Test {
|
||||
|
||||
// comment2
|
||||
System.out.println("hello");
|
||||
/*in return */
|
||||
/*in return */
|
||||
String s = "foo" + //inline
|
||||
"bar";
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@ import java.util.function.Function;
|
||||
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
/* bar */
|
||||
/* who-hoo */
|
||||
/* bar */
|
||||
/* who-hoo */
|
||||
String s = "foo";
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ import java.util.function.Function;
|
||||
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
/* bar */
|
||||
/* bar */
|
||||
String s = ("a" +/* who-hoo */ "x") + "foo";
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
class Test {
|
||||
public int test(String s1, String s2) {
|
||||
return Integer.compare(s1.length(), s2.length());
|
||||
/*otherwise bigger*/
|
||||
/*otherwise bigger*/
|
||||
}
|
||||
|
||||
public int test2(String s1, String s2) {
|
||||
|
||||
+3
-3
@@ -3,9 +3,9 @@ public class Test {
|
||||
public void test(String s1, String s2) {
|
||||
System.out.println(Integer.compare(s1.length(), s2.length()));
|
||||
System.out.println(Integer.compare(s2.length(), s1.length()));
|
||||
/*greater!*/
|
||||
/*less!*/
|
||||
/*equal!*/
|
||||
/*greater!*/
|
||||
/*less!*/
|
||||
/*equal!*/
|
||||
System.out.println(Integer.compare(s1.length(), s2.length()));
|
||||
System.out.println(Integer.compare(s2.length(), s1.length()));
|
||||
System.out.println(Integer.compare(s2.length(), s1.length()));
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.util.Arrays;
|
||||
|
||||
class Test {
|
||||
long cnt() {
|
||||
/*count*/
|
||||
/*count*/
|
||||
return (long) Arrays.asList('d', 'e', 'f')./*stream*/size()/*after*/;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ import java.util.Arrays;
|
||||
|
||||
class Test {
|
||||
int cnt() {
|
||||
/*inside*/
|
||||
/*inside*/
|
||||
return Arrays.asList('d', 'e', 'f').size();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
import java.util.Arrays;
|
||||
|
||||
class Test {
|
||||
/*count*/
|
||||
/*count*/
|
||||
long cnt = (long) Arrays.asList('d', 'e', 'f')./*stream*/size()/*after*/;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ public class Main {
|
||||
private String str;
|
||||
|
||||
public void testGetOrDefault(Map<String, String> map, String key, Main other) {
|
||||
/* output none */
|
||||
/* output none */
|
||||
System.out.println(/* output map value */ map.getOrDefault("k", NONE));
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ public class Test {
|
||||
"d", "1", "e", /* this is also 1*/ "1", "f", "1", "g", "1", // G is important!
|
||||
"h", "1", "i", "1",
|
||||
|
||||
/* Finally J */
|
||||
/* why not putting comment inside the call expression? */"j", "1");
|
||||
/* Finally J */
|
||||
/* why not putting comment inside the call expression? */"j", "1");
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import java.util.stream.Stream;
|
||||
|
||||
public class Test {
|
||||
public void test() {
|
||||
/*redundant*/
|
||||
/*redundant*/
|
||||
System.out.println(Stream.of(/*just one number*/123).count());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ public class Main {
|
||||
|
||||
public boolean ternaryFnMrGenericComment(List<String> list, Function<String, Boolean> fn, boolean b) {
|
||||
return list.stream().allMatch(b ? // select
|
||||
/* comment */ String::isEmpty :
|
||||
/* comment2 */fn::apply);
|
||||
/* comment */ String::isEmpty :
|
||||
/* comment2 */fn::apply);
|
||||
}
|
||||
|
||||
public <T extends Boolean> boolean doubleTernaryMr(List<String> list, boolean b, boolean b2) {
|
||||
@@ -49,7 +49,7 @@ public class Main {
|
||||
}
|
||||
|
||||
public boolean anyMatchBooleanValue(List<String> list) {
|
||||
/* ditto boolean!*/
|
||||
/* ditto boolean!*/
|
||||
return list.stream().anyMatch(String::isEmpty);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.util.List;
|
||||
public class Main {
|
||||
void test(List<String> list) {
|
||||
// hello
|
||||
/* in return */
|
||||
/* in return */
|
||||
long count = list.stream()
|
||||
.peek(System.out::println)
|
||||
.count();
|
||||
|
||||
+13
-13
@@ -3,17 +3,17 @@
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
void test(List<String> list) {
|
||||
long count = list.stream()
|
||||
.peek(e -> {
|
||||
if(e.isEmpty()) {
|
||||
System.out.println("Empty line passed!");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
// hello
|
||||
/* in return */
|
||||
})
|
||||
.count();
|
||||
System.out.println(count);
|
||||
}
|
||||
void test(List<String> list) {
|
||||
long count = list.stream()
|
||||
.peek(e -> {
|
||||
if(e.isEmpty()) {
|
||||
System.out.println("Empty line passed!");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
// hello
|
||||
/* in return */
|
||||
})
|
||||
.count();
|
||||
System.out.println(count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.util.*;
|
||||
|
||||
class Test {
|
||||
public void testToArray(List<String[]> data) {
|
||||
/*generate array*/
|
||||
/*generate array*/
|
||||
String[][] array = data.subList(0, /*max number*/ 10).toArray(new String[0][]);
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -3,17 +3,17 @@
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
void test(List<String> list) {
|
||||
long count = list.stream()
|
||||
.ma<caret>p(e -> {
|
||||
if(e.isEmpty()) {
|
||||
System.out.println("Empty line passed!");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
// hello
|
||||
return /* in return */ e;
|
||||
})
|
||||
.count();
|
||||
System.out.println(count);
|
||||
}
|
||||
void test(List<String> list) {
|
||||
long count = list.stream()
|
||||
.ma<caret>p(e -> {
|
||||
if(e.isEmpty()) {
|
||||
System.out.println("Empty line passed!");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
// hello
|
||||
return /* in return */ e;
|
||||
})
|
||||
.count();
|
||||
System.out.println(count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
class Test {
|
||||
/*
|
||||
*/
|
||||
/*
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class Test{
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
class Test {
|
||||
/*and comment here*///comment
|
||||
/*and comment here*///comment
|
||||
public static final String xxx = "";
|
||||
|
||||
{
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest {
|
||||
" AAAAAA.b()\n" +
|
||||
" .c()\n" +
|
||||
" .d()\n" +
|
||||
" /* simple block comment */\n" +
|
||||
" /* simple block comment */\n" +
|
||||
" .e();\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
|
||||
+1
-1
@@ -603,7 +603,7 @@ public class JavaFormatterIndentationTest extends AbstractJavaFormatterTest {
|
||||
|
||||
String expected =
|
||||
"/*\n" +
|
||||
"\t* comment\n" +
|
||||
" * comment\n" +
|
||||
" */\n" +
|
||||
"class Test {\n" +
|
||||
"}";
|
||||
|
||||
@@ -3388,5 +3388,20 @@ public void testSCR260() throws Exception {
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
public void testFormatCStyleCommentWithAsterisks() {
|
||||
doMethodTest(
|
||||
" for (Object o : new Object[]{}) {\n" +
|
||||
"/*\n" +
|
||||
" *\n" +
|
||||
" \t\t\t\t\t */\n" +
|
||||
" }\n",
|
||||
"for (Object o : new Object[]{}) {\n" +
|
||||
" /*\n" +
|
||||
" *\n" +
|
||||
" */\n" +
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -128,6 +128,10 @@ public class TabIndentingTest extends LightIdeaTestCase {
|
||||
doTest("SCR6197.java", "SCR6197_after.java");
|
||||
}
|
||||
|
||||
public void testMoreTabsInComments() throws Exception {
|
||||
doTest("moreTabsInComments.java", "moreTabsInComments_after.java");
|
||||
}
|
||||
|
||||
private void doTest(String fileNameBefore, String fileNameAfter) throws Exception {
|
||||
String text = loadFile(fileNameBefore);
|
||||
final PsiFile file = createFile(fileNameBefore, text);
|
||||
|
||||
@@ -73,6 +73,10 @@ public interface TestFramework {
|
||||
* should be checked for abstract method error
|
||||
*/
|
||||
boolean isTestMethod(PsiElement element);
|
||||
|
||||
default boolean isTestMethod(PsiElement element, boolean checkAbstract) {
|
||||
return isTestMethod(element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Language getLanguage();
|
||||
|
||||
@@ -57,11 +57,17 @@ public class AutoPopupController implements Disposable {
|
||||
*/
|
||||
public static final Key<Boolean> ALWAYS_AUTO_POPUP = Key.create("Always Show Completion Auto-Popup");
|
||||
/**
|
||||
* If editor has Boolean.TRUE by this key completion popup would be shown every time when editor gets focus
|
||||
* and the popup wouldn't have advertising text in bottom.
|
||||
* For example this key can be used for TextFieldWithAutoCompletion. (It looks like usual JTextField and completion shortcut is not obvious to be active.)
|
||||
* If editor has Boolean.TRUE by this key completion popup would be shown without advertising text at the bottom.
|
||||
*/
|
||||
public static final Key<Boolean> ALWAYS_AUTO_POPUP_NO_ADS = Key.create("Always Show Completion Auto-Popup");
|
||||
public static final Key<Boolean> NO_ADS = Key.create("Show Completion Auto-Popup without Ads");
|
||||
|
||||
/**
|
||||
* If editor has Boolean.TRUE by this key completion popup would be shown every time when editor gets focus.
|
||||
* For example this key can be used for TextFieldWithAutoCompletion.
|
||||
* (TextFieldWithAutoCompletion looks like standard JTextField and completion shortcut is not obvious to be active)
|
||||
*/
|
||||
public static final Key<Boolean> AUTO_POPUP_ON_FOCUS_GAINED = Key.create("Show Completion Auto-Popup On Focus Gained");
|
||||
|
||||
|
||||
private final Project myProject;
|
||||
private final Alarm myAlarm = new Alarm();
|
||||
@@ -109,7 +115,7 @@ public class AutoPopupController implements Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean alwaysAutoPopup = editor != null && (Boolean.TRUE.equals(editor.getUserData(ALWAYS_AUTO_POPUP)) || Boolean.TRUE.equals(editor.getUserData(ALWAYS_AUTO_POPUP_NO_ADS)));
|
||||
boolean alwaysAutoPopup = editor != null && Boolean.TRUE.equals(editor.getUserData(ALWAYS_AUTO_POPUP));
|
||||
if (!CodeInsightSettings.getInstance().AUTO_POPUP_COMPLETION_LOOKUP && !alwaysAutoPopup) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -683,7 +683,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
}
|
||||
|
||||
myAdComponent.showRandomText();
|
||||
if (Boolean.TRUE.equals(myEditor.getUserData(AutoPopupController.ALWAYS_AUTO_POPUP_NO_ADS))) {
|
||||
if (Boolean.TRUE.equals(myEditor.getUserData(AutoPopupController.NO_ADS))) {
|
||||
myAdComponent.clearAdvertisements();
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ public class LanguageConsoleImpl extends ConsoleViewImpl implements LanguageCons
|
||||
myCurrentEditor = myConsoleEditor;
|
||||
Document historyDocument = ((EditorFactoryImpl)editorFactory).createDocument(true);
|
||||
UndoUtil.disableUndoFor(historyDocument);
|
||||
myHistoryViewer = (EditorEx)editorFactory.createViewer(historyDocument, getProject());
|
||||
myHistoryViewer = (EditorEx)editorFactory.createViewer(historyDocument, getProject(), EditorKind.CONSOLE);
|
||||
myHistoryViewer.getDocument().addDocumentListener(myDocumentAdapter);
|
||||
|
||||
myScrollBar.setOpaque(false);
|
||||
|
||||
@@ -320,7 +320,9 @@ public class FindPopupPanel extends JBPanel implements FindUI, DataProvider {
|
||||
@Override
|
||||
protected EditorEx createEditor() {
|
||||
EditorEx editor = super.createEditor();
|
||||
editor.putUserData(AutoPopupController.ALWAYS_AUTO_POPUP_NO_ADS, Boolean.TRUE);
|
||||
editor.putUserData(AutoPopupController.ALWAYS_AUTO_POPUP, Boolean.TRUE);
|
||||
editor.putUserData(AutoPopupController.NO_ADS, Boolean.TRUE);
|
||||
editor.putUserData(AutoPopupController.AUTO_POPUP_ON_FOCUS_GAINED, Boolean.TRUE);
|
||||
return editor;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.formatting.blocks
|
||||
|
||||
import com.intellij.formatting.*
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.TokenType
|
||||
import com.intellij.psi.formatter.common.AbstractBlock
|
||||
|
||||
|
||||
fun ASTNode.prev(): ASTNode? {
|
||||
var prev = treePrev
|
||||
while (prev != null && prev.elementType == TokenType.WHITE_SPACE) {
|
||||
prev = prev.treePrev
|
||||
}
|
||||
if (prev != null) return prev
|
||||
return if (treeParent != null) treeParent.prev() else null
|
||||
}
|
||||
|
||||
|
||||
class CStyleCommentBlock(comment: ASTNode, private val indent: Indent?): AbstractBlock(comment, null, null) {
|
||||
|
||||
private val lines by lazy { lineBlocks() }
|
||||
val isCommentFormattable by lazy {
|
||||
lines.drop(1).all { it.text.startsWith("*") }
|
||||
}
|
||||
|
||||
val spacing: Spacing?
|
||||
get() = if (isCommentFormattable) null else Spacing.getReadOnlySpacing()
|
||||
|
||||
override fun getSpacing(child1: Block?, child2: Block): Spacing? {
|
||||
val isLicenseComment = child1 == null && node.prev() == null
|
||||
if (isLicenseComment) {
|
||||
return Spacing.getReadOnlySpacing()
|
||||
}
|
||||
|
||||
return child2.getSpacing(null, this)
|
||||
}
|
||||
|
||||
override fun getIndent() = indent
|
||||
|
||||
override fun buildChildren(): List<Block> {
|
||||
if (!isCommentFormattable) return emptyList()
|
||||
|
||||
return lines.map {
|
||||
val text = it.text
|
||||
val indent = when {
|
||||
!isCommentFormattable -> null
|
||||
text.startsWith("/*") -> Indent.getNoneIndent()
|
||||
else -> Indent.getSpaceIndent(1)
|
||||
}
|
||||
TextLineBlock(text, it.textRange, null, indent, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun lineBlocks(): List<LineInfo> {
|
||||
return node.text
|
||||
.mapIndexed { index, char -> index to char }
|
||||
.split { it.second == '\n' }
|
||||
.mapNotNull {
|
||||
val block = it.dropWhile { Character.isWhitespace(it.second) }
|
||||
if (block.isEmpty()) return@mapNotNull null
|
||||
|
||||
val text = block.map { it.second }.joinToString("").trimEnd()
|
||||
|
||||
val startOffset = node.startOffset + block.first().first
|
||||
val range = TextRange(startOffset, startOffset + text.length)
|
||||
|
||||
LineInfo(text, range)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isLeaf() = !isCommentFormattable
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class LineInfo(val text: String, val textRange: TextRange)
|
||||
|
||||
|
||||
class TextLineBlock(
|
||||
val text: String,
|
||||
private val textRange: TextRange,
|
||||
private val alignment: Alignment?,
|
||||
private val indent: Indent?,
|
||||
val spacing: Spacing?
|
||||
) : Block {
|
||||
|
||||
override fun getTextRange(): TextRange {
|
||||
return textRange
|
||||
}
|
||||
|
||||
override fun getSubBlocks(): List<Block> = emptyList()
|
||||
|
||||
override fun getWrap() = null
|
||||
|
||||
override fun getIndent() = indent
|
||||
|
||||
override fun getAlignment() = alignment
|
||||
|
||||
override fun getSpacing(child1: Block?, child2: Block) = spacing
|
||||
|
||||
override fun getChildAttributes(newChildIndex: Int): ChildAttributes {
|
||||
throw UnsupportedOperationException("Should not be called")
|
||||
}
|
||||
|
||||
override fun isIncomplete() = false
|
||||
|
||||
override fun isLeaf() = true
|
||||
|
||||
override fun toString(): String {
|
||||
return "TextLineBlock(text='$text', textRange=$textRange)"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun <T> List<T>.split(predicate: (T) -> Boolean): List<List<T>> {
|
||||
if (indices.isEmpty()) return listOf()
|
||||
val result = mutableListOf<List<T>>()
|
||||
|
||||
val current = mutableListOf<T>()
|
||||
for (e in this) {
|
||||
if (predicate(e)) {
|
||||
result.add(current.toList())
|
||||
current.clear()
|
||||
}
|
||||
else {
|
||||
current.add(e)
|
||||
}
|
||||
}
|
||||
|
||||
if (current.isNotEmpty()) {
|
||||
result.add(current)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -307,6 +307,12 @@ public class FormatterUtil {
|
||||
@Nullable final TextRange textRange) {
|
||||
final CharTable charTable = SharedImplUtil.findCharTableByTree(leafElement);
|
||||
|
||||
if (textRange != null && textRange.getStartOffset() > leafElement.getTextRange().getStartOffset() &&
|
||||
textRange.getEndOffset() < leafElement.getTextRange().getEndOffset()) {
|
||||
replaceInnerWhiteSpace(whiteSpace, leafElement, textRange);
|
||||
return;
|
||||
}
|
||||
|
||||
ASTNode treePrev = findPreviousWhiteSpace(leafElement, whiteSpaceToken);
|
||||
if (treePrev == null) {
|
||||
treePrev = getWsCandidate(leafElement);
|
||||
|
||||
@@ -23,10 +23,7 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
@@ -88,31 +85,52 @@ public class PsiBasedFormattingModel implements FormattingModelEx {
|
||||
ASTNode leafElement = findElementAt(offset);
|
||||
|
||||
if (leafElement != null) {
|
||||
PsiFile hostFile = myASTNode.getPsi().getContainingFile();
|
||||
PsiElement injectedElement = InjectedLanguageUtil.findInjectedElementNoCommit(hostFile, offset);
|
||||
|
||||
TextRange effectiveRange = injectedElement != null ? rangeInInjectedDocument(textRange, injectedElement) : null;
|
||||
if (effectiveRange == null) {
|
||||
effectiveRange = textRange;
|
||||
}
|
||||
|
||||
if (leafElement.getPsi() instanceof PsiFile) {
|
||||
return null;
|
||||
} else {
|
||||
if (!leafElement.getPsi().isValid()) {
|
||||
String message = "Invalid element found in '\n" +
|
||||
myASTNode.getText() +
|
||||
"\n' at " +
|
||||
offset +
|
||||
"(" +
|
||||
myASTNode.getText().substring(offset, Math.min(offset + 10, myASTNode.getTextLength()));
|
||||
LOG.error(message);
|
||||
}
|
||||
return replaceWithPsiInLeaf(textRange, whiteSpace, leafElement);
|
||||
LOG.assertTrue(leafElement.getPsi().isValid());
|
||||
return replaceWithPsiInLeaf(effectiveRange, whiteSpace, leafElement);
|
||||
}
|
||||
} else if (textRange.getEndOffset() == myASTNode.getTextLength()){
|
||||
|
||||
}
|
||||
else if (textRange.getEndOffset() == myASTNode.getTextLength()){
|
||||
CodeStyleManager.getInstance(myProject).performActionWithFormatterDisabled(
|
||||
(Runnable)() -> FormatterUtil.replaceLastWhiteSpace(myASTNode, whiteSpace, textRange));
|
||||
|
||||
(Runnable)() -> FormatterUtil.replaceLastWhiteSpace(myASTNode, whiteSpace, textRange)
|
||||
);
|
||||
return whiteSpace;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static TextRange rangeInInjectedDocument(TextRange textRange, PsiElement injectedElement) {
|
||||
PsiLanguageInjectionHost host = InjectedLanguageUtil.findInjectionHost(injectedElement);
|
||||
if (host == null) return null;
|
||||
|
||||
ElementManipulator<PsiLanguageInjectionHost> manipulator = ElementManipulators.getManipulator(host);
|
||||
if (manipulator == null) return null;
|
||||
|
||||
final TextRange injectionRangeInHost = manipulator.getRangeInElement(host);
|
||||
final int hostStartOffset = host.getTextRange().getStartOffset();
|
||||
|
||||
final int injectedDocumentStartOffset = hostStartOffset + injectionRangeInHost.getStartOffset();
|
||||
final int injectedDocumentEndOffset = hostStartOffset + injectionRangeInHost.getEndOffset();
|
||||
|
||||
if (textRange.getEndOffset() < injectedDocumentStartOffset || textRange.getStartOffset() > injectedDocumentEndOffset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return textRange.shiftLeft(injectedDocumentStartOffset);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String replaceWithPsiInLeaf(final TextRange textRange, final String whiteSpace, final ASTNode leafElement) {
|
||||
if (!myCanModifyAllWhiteSpaces) {
|
||||
@@ -129,12 +147,17 @@ public class PsiBasedFormattingModel implements FormattingModelEx {
|
||||
protected ASTNode findElementAt(final int offset) {
|
||||
PsiFile containingFile = myASTNode.getPsi().getContainingFile();
|
||||
Project project = containingFile.getProject();
|
||||
|
||||
assert !PsiDocumentManager.getInstance(project).isUncommited(myDocumentModel.getDocument());
|
||||
// TODO:default project can not be used for injections, because latter might wants (unavailable) indices
|
||||
|
||||
PsiElement psiElement = project.isDefault() ? null : InjectedLanguageUtil.findInjectedElementNoCommit(containingFile, offset);
|
||||
if (psiElement == null) psiElement = containingFile.findElementAt(offset);
|
||||
if (psiElement == null) return null;
|
||||
return psiElement.getNode();
|
||||
if (psiElement != null) {
|
||||
return psiElement.getNode();
|
||||
}
|
||||
|
||||
psiElement = containingFile.findElementAt(offset);
|
||||
return psiElement != null ? psiElement.getNode() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -70,7 +70,7 @@ public class TextCompletionUtil {
|
||||
editor.addFocusListener(new FocusChangeListener() {
|
||||
@Override
|
||||
public void focusGained(final Editor editor) {
|
||||
if (Boolean.TRUE.equals(editor.getUserData(AutoPopupController.ALWAYS_AUTO_POPUP_NO_ADS))) {
|
||||
if (Boolean.TRUE.equals(editor.getUserData(AutoPopupController.AUTO_POPUP_ON_FOCUS_GAINED))) {
|
||||
AutoPopupController.getInstance(editor.getProject()).scheduleAutoPopup(editor);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
|
||||
import com.intellij.util.TimeoutUtil;
|
||||
@@ -33,6 +34,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -42,7 +44,7 @@ class AsyncFilterRunner {
|
||||
private static final ExecutorService ourExecutor = AppExecutorUtil.createBoundedApplicationPoolExecutor("console filters", 1);
|
||||
private final EditorHyperlinkSupport myHyperlinks;
|
||||
private final Editor myEditor;
|
||||
private final Queue<LineHighlighter> myQueue = new ConcurrentLinkedQueue<>();
|
||||
private final Queue<HighlighterJob> myQueue = new ConcurrentLinkedQueue<>();
|
||||
@NotNull private List<FilterResult> myResults = new ArrayList<>();
|
||||
|
||||
AsyncFilterRunner(EditorHyperlinkSupport hyperlinks, Editor editor) {
|
||||
@@ -53,7 +55,7 @@ class AsyncFilterRunner {
|
||||
void highlightHyperlinks(final Filter customFilter, final int startLine, final int endLine) {
|
||||
if (endLine < 0) return;
|
||||
|
||||
queueTasks(customFilter, startLine, endLine);
|
||||
myQueue.offer(new HighlighterJob(customFilter, startLine, endLine, myEditor.getDocument()));
|
||||
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
|
||||
runTasks();
|
||||
highlightAvailableResults();
|
||||
@@ -139,42 +141,15 @@ class AsyncFilterRunner {
|
||||
}
|
||||
}
|
||||
|
||||
private void queueTasks(Filter filter, int startLine, int endLine) {
|
||||
Document document = myEditor.getDocument();
|
||||
int markerOffset = document.getLineEndOffset(endLine);
|
||||
RangeMarker marker = document.createRangeMarker(markerOffset, markerOffset);
|
||||
for (int line = startLine; line <= endLine; line++) {
|
||||
myQueue.offer(processLine(document, filter, line, markerOffset, marker));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private LineHighlighter processLine(Document document, Filter filter, int line, int initialMarkerOffset, RangeMarker marker) {
|
||||
int lineEnd = document.getLineEndOffset(line);
|
||||
int endOffset = lineEnd + (lineEnd < document.getTextLength() ? 1 /* for \n */ : 0);
|
||||
CharSequence text = EditorHyperlinkSupport.getLineSequence(document, line, true);
|
||||
return () -> runFilterForLine(initialMarkerOffset, marker, filter, endOffset, text);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FilterResult runFilterForLine(int initialMarkerOffset, RangeMarker marker, Filter filter, int endOffset, CharSequence lineText) {
|
||||
if (!marker.isValid() || marker.getEndOffset() == 0) return null;
|
||||
|
||||
Filter.Result result = checkRange(filter, endOffset, filter.applyFilter(lineText.toString(), endOffset));
|
||||
return result == null ? null : () -> {
|
||||
if (marker.isValid()) {
|
||||
myHyperlinks.highlightHyperlinks(result, marker.getStartOffset() - initialMarkerOffset);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void runTasks() {
|
||||
if (myEditor.isDisposed()) return;
|
||||
|
||||
while (!myQueue.isEmpty()) {
|
||||
ProgressManager.checkCanceled();
|
||||
LineHighlighter highlighter = myQueue.peek();
|
||||
addLineResult(highlighter.runFilterForLine());
|
||||
HighlighterJob highlighter = myQueue.peek();
|
||||
while (highlighter.hasUnprocessedLines()) {
|
||||
ProgressManager.checkCanceled();
|
||||
addLineResult(highlighter.analyzeNextLine());
|
||||
}
|
||||
LOG.assertTrue(highlighter == myQueue.remove());
|
||||
}
|
||||
}
|
||||
@@ -192,12 +167,61 @@ class AsyncFilterRunner {
|
||||
return result;
|
||||
}
|
||||
|
||||
private interface LineHighlighter {
|
||||
@Nullable FilterResult runFilterForLine();
|
||||
}
|
||||
|
||||
private interface FilterResult {
|
||||
void applyHighlights();
|
||||
}
|
||||
|
||||
private class HighlighterJob {
|
||||
private AtomicInteger startLine;
|
||||
private final int endLine;
|
||||
private final int initialMarkerOffset;
|
||||
private final RangeMarker endMarker;
|
||||
private final Filter filter;
|
||||
private final Document snapshot;
|
||||
|
||||
HighlighterJob(Filter filter, int startLine, int endLine, Document document) {
|
||||
this.startLine = new AtomicInteger(startLine);
|
||||
this.endLine = endLine;
|
||||
this.filter = filter;
|
||||
|
||||
initialMarkerOffset = document.getLineEndOffset(endLine);
|
||||
endMarker = document.createRangeMarker(initialMarkerOffset, initialMarkerOffset);
|
||||
snapshot = ((DocumentImpl)document).freeze();
|
||||
}
|
||||
|
||||
boolean hasUnprocessedLines() {
|
||||
return !isOutdated() && startLine.get() <= endLine;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
AsyncFilterRunner.FilterResult analyzeNextLine() {
|
||||
int line = startLine.get();
|
||||
Filter.Result result = analyzeLine(line);
|
||||
LOG.assertTrue(line == startLine.getAndIncrement());
|
||||
return result == null ? null : () -> {
|
||||
if (!isOutdated()) {
|
||||
myHyperlinks.highlightHyperlinks(result, getOffsetDelta());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Filter.Result analyzeLine(int line) {
|
||||
int lineStart = snapshot.getLineStartOffset(line);
|
||||
if (lineStart + getOffsetDelta() < 0) return null;
|
||||
|
||||
String lineText = EditorHyperlinkSupport.getLineText(snapshot, line, true);
|
||||
int endOffset = lineStart + lineText.length();
|
||||
return checkRange(filter, endOffset, filter.applyFilter(lineText, endOffset));
|
||||
}
|
||||
|
||||
boolean isOutdated() {
|
||||
return !endMarker.isValid() || endMarker.getEndOffset() == 0;
|
||||
}
|
||||
|
||||
int getOffsetDelta() {
|
||||
return endMarker.getStartOffset() - initialMarkerOffset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-7
@@ -209,11 +209,16 @@ public class ConsoleViewImplTest extends LightPlatformTestCase {
|
||||
|
||||
@NotNull
|
||||
static ConsoleViewImpl createConsole() {
|
||||
return createConsole(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ConsoleViewImpl createConsole(boolean usePredefinedMessageFilter) {
|
||||
Project project = getProject();
|
||||
ConsoleViewImpl console = new ConsoleViewImpl(project,
|
||||
GlobalSearchScope.allScope(project),
|
||||
false,
|
||||
false);
|
||||
usePredefinedMessageFilter);
|
||||
console.getComponent(); // initConsoleEditor()
|
||||
ProcessHandler processHandler = new NopProcessHandler();
|
||||
processHandler.startNotify();
|
||||
@@ -235,9 +240,21 @@ public class ConsoleViewImplTest extends LightPlatformTestCase {
|
||||
}).assertTiming());
|
||||
}
|
||||
|
||||
public void testLargeConsolePerformance() throws Exception {
|
||||
withCycleConsole(UISettings.getInstance().getConsoleCycleBufferSizeKb(), console ->
|
||||
PlatformTestUtil.startPerformanceTest("console print", 9000, () -> {
|
||||
console.clear();
|
||||
for (int i=0; i<10_000_000; i++) {
|
||||
console.print("hello\n", ConsoleViewContentType.NORMAL_OUTPUT);
|
||||
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue();
|
||||
}
|
||||
console.waitAllRequests();
|
||||
}).assertTiming());
|
||||
}
|
||||
|
||||
public void testPerformanceOfMergeableTokens() throws Exception {
|
||||
withCycleConsole(1000, console ->
|
||||
PlatformTestUtil.startPerformanceTest("console print", 5500, () -> {
|
||||
PlatformTestUtil.startPerformanceTest("console print", 3500, () -> {
|
||||
console.clear();
|
||||
for (int i=0; i<10_000_000; i++) {
|
||||
console.print("xxx\n", ConsoleViewContentType.NORMAL_OUTPUT);
|
||||
@@ -257,12 +274,8 @@ public class ConsoleViewImplTest extends LightPlatformTestCase {
|
||||
UISettings.getInstance().setOverrideConsoleCycleBufferSize(true);
|
||||
UISettings.getInstance().setConsoleCycleBufferSizeKb(capacityKB);
|
||||
// create new to reflect changed buffer size
|
||||
ConsoleViewImpl console = createConsole();
|
||||
ConsoleViewImpl console = createConsole(true);
|
||||
try {
|
||||
ConsoleBuffer.useCycleBuffer();
|
||||
ConsoleBuffer.getCycleBufferSize();
|
||||
UISettings.getInstance();// instantiate early
|
||||
|
||||
runnable.consume(console);
|
||||
}
|
||||
finally {
|
||||
|
||||
+6
@@ -196,6 +196,12 @@ aaa bbb ccc
|
||||
"0123456789 ")
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `test first spacing object is used`() {
|
||||
doReformatTest("[]0 [s_min5_max5]([s_min10_max10]1)", "0 1")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test no wrap object no text wrap`() {
|
||||
doReformatTest("[]aaa []bbb []ccc []ddd []eee []f|ff", "aaa bbb ccc ddd eee fff")
|
||||
|
||||
@@ -133,6 +133,12 @@ public class TextRange implements Segment, Serializable {
|
||||
return new TextRange(myStartOffset + delta, myEndOffset + delta);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TextRange shiftLeft(int delta) {
|
||||
if (delta == 0) return this;
|
||||
return new TextRange(myStartOffset - delta, myEndOffset - delta);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TextRange grown(int lengthDelta) {
|
||||
return from(myStartOffset, getLength() + lengthDelta);
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ public class TestUtils {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) return false;
|
||||
final TestFramework framework = TestFrameworks.detectFramework(containingClass);
|
||||
return framework != null && framework.getName().startsWith("JUnit") && framework.isTestMethod(method);
|
||||
return framework != null && framework.getName().startsWith("JUnit") && framework.isTestMethod(method, false);
|
||||
}
|
||||
|
||||
public static boolean isRunnable(PsiMethod method) {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
class Comment3 {{
|
||||
int i = 8;
|
||||
/*giant*/
|
||||
/*giant*/
|
||||
String t = "killer" +/*robots*/"with laser eyes" + //coming
|
||||
i + //to
|
||||
"\n" + //destroy
|
||||
|
||||
+7
-1
@@ -16,4 +16,10 @@ public class <warning descr="JUnit test case 'TestCaseWithNoTestMethods' has no
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractTest extends junit.framework.TestCase {
|
||||
public void testInAbstract() {}
|
||||
}
|
||||
|
||||
class MyImplTest extends AbstractTest {}
|
||||
+3
-1
@@ -29,7 +29,9 @@ public class TestCaseWithNoTestMethodsInspectionTest extends LightInspectionTest
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
return new TestCaseWithNoTestMethodsInspection();
|
||||
TestCaseWithNoTestMethodsInspection inspection = new TestCaseWithNoTestMethodsInspection();
|
||||
inspection.ignoreSupers = true;
|
||||
return inspection;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -280,8 +280,8 @@ def run_python_code_windows(pid, python_code, connect_debugger_tracing=False, sh
|
||||
|
||||
if is_64 != is_python_64bit():
|
||||
raise RuntimeError("The architecture of the Python used to connect doesn't match the architecture of the target.\n"
|
||||
"Target 64 bits: %s\n"
|
||||
"Current Python 64 bits: %s" % (is_64, is_python_64bit()))
|
||||
"Target 64 bits: %s\n"
|
||||
"Current Python 64 bits: %s" % (is_64, is_python_64bit()))
|
||||
|
||||
print('Connecting to %s bits target' % (bits,))
|
||||
assert resolve_label(process, compat.b('PyGILState_Ensure'))
|
||||
@@ -366,16 +366,16 @@ def run_python_code_windows(pid, python_code, connect_debugger_tracing=False, sh
|
||||
|
||||
|
||||
# Uncomment to see the disassembled version of what we just did...
|
||||
# with open('f.asm', 'wb') as stream:
|
||||
# stream.write(code)
|
||||
#
|
||||
# exe = r'x:\nasm\nasm-2.07-win32\nasm-2.07\ndisasm.exe'
|
||||
# if is_64:
|
||||
# arch = '64'
|
||||
# else:
|
||||
# arch = '32'
|
||||
#
|
||||
# subprocess.call((exe + ' -b %s f.asm' % arch).split())
|
||||
# with open('f.asm', 'wb') as stream:
|
||||
# stream.write(code)
|
||||
#
|
||||
# exe = r'x:\nasm\nasm-2.07-win32\nasm-2.07\ndisasm.exe'
|
||||
# if is_64:
|
||||
# arch = '64'
|
||||
# else:
|
||||
# arch = '32'
|
||||
#
|
||||
# subprocess.call((exe + ' -b %s f.asm' % arch).split())
|
||||
|
||||
print('Injecting code to target process')
|
||||
thread, _thread_address = process.inject_code(code, 0)
|
||||
@@ -428,11 +428,11 @@ def run_python_code_linux(pid, python_code, connect_debugger_tracing=False, show
|
||||
'--nw', # no gui interface
|
||||
'--nh', # no ~/.gdbinit
|
||||
'--nx', # no .gdbinit
|
||||
# '--quiet', # no version number on startup
|
||||
# '--quiet', # no version number on startup
|
||||
'--pid',
|
||||
str(pid),
|
||||
'--batch',
|
||||
# '--batch-silent',
|
||||
# '--batch-silent',
|
||||
]
|
||||
|
||||
cmd.extend(["--eval-command='set scheduler-locking off'"]) # If on we'll deadlock.
|
||||
@@ -449,7 +449,7 @@ def run_python_code_linux(pid, python_code, connect_debugger_tracing=False, show
|
||||
if connect_debugger_tracing:
|
||||
cmd.extend([
|
||||
"--command='%s'" % (gdb_threads_settrace_file,),
|
||||
])
|
||||
])
|
||||
|
||||
#print ' '.join(cmd)
|
||||
|
||||
@@ -527,8 +527,8 @@ def run_python_code_mac(pid, python_code, connect_debugger_tracing=False, show_d
|
||||
"-o 'process attach --pid %d'"%pid,
|
||||
"-o 'command script import \"%s\"'" % (lldb_prepare_file,),
|
||||
"-o 'load_lib_and_attach \"%s\" %s \"%s\" %s'" % (target_dll,
|
||||
is_debug, python_code, show_debug_info),
|
||||
])
|
||||
is_debug, python_code, show_debug_info),
|
||||
])
|
||||
|
||||
|
||||
if connect_debugger_tracing:
|
||||
@@ -556,7 +556,7 @@ def run_python_code_mac(pid, python_code, connect_debugger_tracing=False, show_d
|
||||
env=env,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
)
|
||||
print('Running lldb in target process.')
|
||||
out, err = p.communicate()
|
||||
print('stdout: %s' % (out,))
|
||||
|
||||
Binary file not shown.
Executable → Regular
BIN
Binary file not shown.
Executable → Regular
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -594,16 +594,6 @@ void IncRef(PyObject* object) {
|
||||
object->ob_refcnt++;
|
||||
}
|
||||
|
||||
// Structure for our shared memory communication, aligned to be identical on 64-bit and 32-bit
|
||||
struct MemoryBuffer {
|
||||
int PortNumber; // offset 0-4
|
||||
__declspec(align(8)) HANDLE AttachStartingEvent; // offset 8 - 16
|
||||
__declspec(align(8)) HANDLE AttachDoneEvent; // offset 16 - 24
|
||||
__declspec(align(8)) int ErrorNumber; // offset 24-28
|
||||
int VersionNumber; // offset 28-32
|
||||
char DebugId[1]; // null terminated string
|
||||
};
|
||||
|
||||
|
||||
// Ensures handles are closed when they go out of scope
|
||||
class HandleHolder {
|
||||
@@ -623,8 +613,8 @@ long GetPythonThreadId(PythonVersion version, PyThreadState* curThread) {
|
||||
threadId = ((PyThreadState_25_27*)curThread)->thread_id;
|
||||
} else if (PyThreadState_30_33::IsFor(version)) {
|
||||
threadId = ((PyThreadState_30_33*)curThread)->thread_id;
|
||||
} else if (PyThreadState_34::IsFor(version)) {
|
||||
threadId = ((PyThreadState_34*)curThread)->thread_id;
|
||||
} else if (PyThreadState_34_36::IsFor(version)) {
|
||||
threadId = ((PyThreadState_34_36*)curThread)->thread_id;
|
||||
}
|
||||
return threadId;
|
||||
}
|
||||
@@ -1201,8 +1191,8 @@ extern "C"
|
||||
frame = ((PyThreadState_25_27*)curThread)->frame;
|
||||
} else if (PyThreadState_30_33::IsFor(version)) {
|
||||
frame = ((PyThreadState_30_33*)curThread)->frame;
|
||||
} else if (PyThreadState_34::IsFor(version)) {
|
||||
frame = ((PyThreadState_34*)curThread)->frame;
|
||||
} else if (PyThreadState_34_36::IsFor(version)) {
|
||||
frame = ((PyThreadState_34_36*)curThread)->frame;
|
||||
}else{
|
||||
if(showDebugInfo){
|
||||
std::cout << "Python version not handled! " << version << std::endl << std::flush;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
|
||||
cl -DUNICODE -D_UNICODE /EHsc /LD attach.cpp /link /out:attach_x86.dll
|
||||
copy attach_x86.dll ..\attach_x86.dll /Y
|
||||
|
||||
|
||||
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64
|
||||
cl -DUNICODE -D_UNICODE /EHsc /LD attach.cpp /link /out:attach_amd64.dll
|
||||
copy attach_amd64.dll ..\attach_amd64.dll /Y
|
||||
@@ -25,7 +25,9 @@ enum PythonVersion {
|
||||
PythonVersion_31 = 0x0301,
|
||||
PythonVersion_32 = 0x0302,
|
||||
PythonVersion_33 = 0x0303,
|
||||
PythonVersion_34 = 0x0304
|
||||
PythonVersion_34 = 0x0304,
|
||||
PythonVersion_35 = 0x0305,
|
||||
PythonVersion_36 = 0x0306
|
||||
};
|
||||
|
||||
|
||||
@@ -110,8 +112,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// 3.3-3.4
|
||||
class PyCodeObject33_34 : public PyObject {
|
||||
// 3.3-3.5
|
||||
class PyCodeObject33_35 : public PyObject {
|
||||
public:
|
||||
int co_argcount; /* #arguments, except *args */
|
||||
int co_kwonlyargcount; /* #keyword only arguments */
|
||||
@@ -133,15 +135,46 @@ public:
|
||||
void *co_zombieframe; /* for optimization only (see frameobject.c) */
|
||||
|
||||
static bool IsFor(int majorVersion, int minorVersion) {
|
||||
return majorVersion == 3 && (minorVersion >= 3 && minorVersion <= 4);
|
||||
return majorVersion == 3 && (minorVersion >= 3 && minorVersion <= 5);
|
||||
}
|
||||
|
||||
static bool IsFor(PythonVersion version) {
|
||||
return version >= PythonVersion_33 && version <= PythonVersion_34;
|
||||
return version >= PythonVersion_33 && version <= PythonVersion_35;
|
||||
}
|
||||
};
|
||||
|
||||
// 2.5 - 3.1
|
||||
// 3.6
|
||||
class PyCodeObject36 : public PyObject {
|
||||
public:
|
||||
int co_argcount; /* #arguments, except *args */
|
||||
int co_kwonlyargcount; /* #keyword only arguments */
|
||||
int co_nlocals; /* #local variables */
|
||||
int co_stacksize; /* #entries needed for evaluation stack */
|
||||
int co_flags; /* CO_..., see below */
|
||||
int co_firstlineno; /* first source line number */
|
||||
PyObject *co_code; /* instruction opcodes */
|
||||
PyObject *co_consts; /* list (constants used) */
|
||||
PyObject *co_names; /* list of strings (names used) */
|
||||
PyObject *co_varnames; /* tuple of strings (local variable names) */
|
||||
PyObject *co_freevars; /* tuple of strings (free variable names) */
|
||||
PyObject *co_cellvars; /* tuple of strings (cell variable names) */
|
||||
/* The rest doesn't count for hash or comparisons */
|
||||
unsigned char *co_cell2arg; /* Maps cell vars which are arguments. */
|
||||
PyObject *co_filename; /* unicode (where it was loaded from) */
|
||||
PyObject *co_name; /* unicode (name, for reference) */
|
||||
PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */
|
||||
void *co_zombieframe; /* for optimization only (see frameobject.c) */
|
||||
|
||||
static bool IsFor(int majorVersion, int minorVersion) {
|
||||
return majorVersion == 3 && minorVersion >= 6;
|
||||
}
|
||||
|
||||
static bool IsFor(PythonVersion version) {
|
||||
return version >= PythonVersion_36;
|
||||
}
|
||||
};
|
||||
|
||||
// 2.5 - 3.6
|
||||
class PyFunctionObject : public PyObject {
|
||||
public:
|
||||
PyObject *func_code; /* A code object */
|
||||
@@ -172,7 +205,7 @@ typedef struct {
|
||||
long hash; /* Hash value; -1 if not set */
|
||||
} PyUnicodeObject;
|
||||
|
||||
// 2.4 - 3.4 compatible
|
||||
// 2.4 - 3.6 compatible
|
||||
class PyFrameObject : public PyVarObject {
|
||||
public:
|
||||
PyFrameObject *f_back; /* previous frame, or NULL */
|
||||
@@ -213,7 +246,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class PyFrameObject34 : public PyFrameObject {
|
||||
class PyFrameObject34_36 : public PyFrameObject {
|
||||
public:
|
||||
/* Borrowed reference to a generator, or NULL */
|
||||
PyObject *f_gen;
|
||||
@@ -228,14 +261,14 @@ public:
|
||||
PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
|
||||
|
||||
static bool IsFor(int majorVersion, int minorVersion) {
|
||||
return majorVersion == 3 && minorVersion == 4;
|
||||
return majorVersion == 3 && minorVersion >= 4 && minorVersion <= 6;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef void (*destructor)(PyObject *);
|
||||
|
||||
// 2.4 - 3.4
|
||||
// 2.4 - 3.6
|
||||
class PyMethodDef {
|
||||
public:
|
||||
char *ml_name; /* The name of the built-in function/method */
|
||||
@@ -243,7 +276,7 @@ public:
|
||||
|
||||
|
||||
//
|
||||
// 2.4 - 3.4, 2.4 has different compat in 64-bit but we don't support any of the released 64-bit platforms (which includes only IA-64)
|
||||
// 2.4 - 3.5, 2.4 has different compat in 64-bit but we don't support any of the released 64-bit platforms (which includes only IA-64)
|
||||
// While these are compatible there are fields only available on later versions.
|
||||
class PyTypeObject : public PyVarObject {
|
||||
public:
|
||||
@@ -256,7 +289,10 @@ public:
|
||||
void* tp_print;
|
||||
void* tp_getattr;
|
||||
void* tp_setattr;
|
||||
void* tp_compare;
|
||||
union {
|
||||
void* tp_compare; /* 2.4 - 3.4 */
|
||||
void* tp_as_async; /* 3.5 - 3.6 */
|
||||
};
|
||||
void* tp_repr;
|
||||
|
||||
/* Method suites for standard classes */
|
||||
@@ -325,7 +361,7 @@ public:
|
||||
unsigned int tp_version_tag;
|
||||
};
|
||||
|
||||
// 2.4 - 3.4
|
||||
// 2.4 - 3.6
|
||||
class PyTupleObject : public PyVarObject {
|
||||
public:
|
||||
PyObject *ob_item[1];
|
||||
@@ -336,7 +372,7 @@ public:
|
||||
*/
|
||||
};
|
||||
|
||||
// 2.4 - 3.4
|
||||
// 2.4 - 3.6
|
||||
class PyCFunctionObject : public PyObject {
|
||||
public:
|
||||
PyMethodDef *m_ml; /* Description of the C function to call */
|
||||
@@ -467,7 +503,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class PyThreadState_34 : public PyThreadState {
|
||||
class PyThreadState_34_36 : public PyThreadState {
|
||||
public:
|
||||
PyThreadState *prev;
|
||||
PyThreadState *next;
|
||||
@@ -507,11 +543,11 @@ public:
|
||||
|
||||
/* XXX signal handlers should also be here */
|
||||
static bool IsFor(int majorVersion, int minorVersion) {
|
||||
return majorVersion == 3 && minorVersion == 4;
|
||||
return majorVersion == 3 && minorVersion >= 4 && minorVersion <= 6;
|
||||
}
|
||||
|
||||
static bool IsFor(PythonVersion version) {
|
||||
return version == PythonVersion_34;
|
||||
return version >= PythonVersion_34 && version <= PythonVersion_36;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -563,6 +599,8 @@ static PythonVersion GetPythonVersion(HMODULE hMod) {
|
||||
case '2': return PythonVersion_32;
|
||||
case '3': return PythonVersion_33;
|
||||
case '4': return PythonVersion_34;
|
||||
case '5': return PythonVersion_35;
|
||||
case '6': return PythonVersion_36;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -570,4 +608,4 @@ static PythonVersion GetPythonVersion(HMODULE hMod) {
|
||||
return PythonVersion_Unknown;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -234,7 +234,7 @@ int _PYDEVD_ExecWithGILSetSysStrace(bool showDebugInfo, bool isDebug){
|
||||
CHECK_NULL(pyImportModFunc, "PyImport_ImportModuleNoBlock not found.\n", 8);
|
||||
|
||||
|
||||
PyObjectHolder pydevdTracingMod = PyObjectHolder(isDebug, pyImportModFunc("pydevd_tracing"));
|
||||
PyObjectHolder pydevdTracingMod = PyObjectHolder(isDebug, pyImportModFunc("_pydevd_bundle.pydevd_tracing"));
|
||||
CHECK_NULL(pydevdTracingMod.ToPython(), "pydevd_tracing module null.\n", 9);
|
||||
|
||||
if(!pyHasAttrFunc(pydevdTracingMod.ToPython(), "_original_settrace")){
|
||||
@@ -271,7 +271,7 @@ int _PYDEVD_ExecWithGILSetSysStrace(bool showDebugInfo, bool isDebug){
|
||||
}
|
||||
return 13;
|
||||
}
|
||||
|
||||
|
||||
PyObjectHolder traceFunc = PyObjectHolder(isDebug, pyGetAttr(globalDbg.ToPython(), "trace_dispatch"));
|
||||
CHECK_NULL(traceFunc.ToPython(), "pydevd.GetGlobalDebugger().trace_dispatch returned null!\n", 14);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
g++ -fPIC -D_REENTRANT -arch x86_64 -I. -c -o attach_linux_x86_64.o attach_linux.c
|
||||
g++ -fPIC -D_REENTRANT -arch x86_64 I. -c -o attach_linux_x86_64.o attach_linux.c
|
||||
g++ -dynamiclib -arch x86_64 -o attach_x86_64.dylib attach_linux_x86_64.o -lc
|
||||
|
||||
|
||||
|
||||
@@ -567,7 +567,7 @@ class System (_ProcessContainer):
|
||||
try:
|
||||
|
||||
# Load a specific dbghelp.dll file
|
||||
debug.system.load_dbghelp("C:\Some folder\dbghelp.dll")
|
||||
debug.system.load_dbghelp("C:\\Some folder\\dbghelp.dll")
|
||||
|
||||
# Start a new process for debugging
|
||||
debug.execv( argv )
|
||||
|
||||
Reference in New Issue
Block a user