Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2017-06-20 15:24:43 +02:00
69 changed files with 574 additions and 230 deletions
+1 -1
View File
@@ -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;
}
@@ -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;
}
@@ -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);
}
}
@@ -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);
}
@@ -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);
}
}
@@ -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();
}
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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
}
@@ -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") {
@@ -10,7 +10,7 @@ public class Test {
// comment2
System.out.println("hello");
/*in return */
/*in return */
String s = "foo" + //inline
"bar";
}
@@ -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";
}
}
@@ -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";
}
}
@@ -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,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*/;
}
}
@@ -4,7 +4,7 @@ import java.util.Arrays;
class Test {
int cnt() {
/*inside*/
/*inside*/
return Arrays.asList('d', 'e', 'f').size();
}
}
@@ -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();
@@ -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][]);
}
}
@@ -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 = "";
{
@@ -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" +
"}");
@@ -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;
}
}
}
@@ -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 {
@@ -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);
@@ -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,6 +1,6 @@
class Comment3 {{
int i = 8;
/*giant*/
/*giant*/
String t = "killer" +/*robots*/"with laser eyes" + //coming
i + //to
"\n" + //destroy
@@ -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 {}
@@ -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.
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 )