Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2014-10-22 17:41:37 +02:00
76 changed files with 815 additions and 369 deletions
@@ -30,6 +30,8 @@ public class RegExpBraceMatcher implements PairedBraceMatcher {
new BracePair(RegExpTT.POS_LOOKBEHIND, RegExpTT.GROUP_END, true), new BracePair(RegExpTT.NEG_LOOKBEHIND, RegExpTT.GROUP_END, true),
new BracePair(RegExpTT.PYTHON_NAMED_GROUP, RegExpTT.GROUP_END, true),
new BracePair(RegExpTT.PYTHON_NAMED_GROUP_REF, RegExpTT.GROUP_END, true),
new BracePair(RegExpTT.RUBY_NAMED_GROUP, RegExpTT.GROUP_END, true),
new BracePair(RegExpTT.RUBY_QUOTED_NAMED_GROUP, RegExpTT.GROUP_END, true),
new BracePair(RegExpTT.CLASS_BEGIN, RegExpTT.CLASS_END, false), new BracePair(RegExpTT.LBRACE, RegExpTT.RBRACE, false),
new BracePair(RegExpTT.QUOTE_BEGIN, RegExpTT.QUOTE_END, false),};
}
@@ -120,6 +120,16 @@ public class RegExpHighlighter extends SyntaxHighlighterBase {
keys1.put(RegExpTT.QUOTE_BEGIN, QUOTE_CHARACTER);
keys1.put(RegExpTT.QUOTE_END, QUOTE_CHARACTER);
keys1.put(RegExpTT.NON_CAPT_GROUP, PARENTHS);
keys1.put(RegExpTT.POS_LOOKBEHIND, PARENTHS);
keys1.put(RegExpTT.NEG_LOOKBEHIND, PARENTHS);
keys1.put(RegExpTT.POS_LOOKAHEAD, PARENTHS);
keys1.put(RegExpTT.NEG_LOOKAHEAD, PARENTHS);
keys1.put(RegExpTT.SET_OPTIONS, PARENTHS);
keys1.put(RegExpTT.PYTHON_NAMED_GROUP, PARENTHS);
keys1.put(RegExpTT.PYTHON_NAMED_GROUP_REF, PARENTHS);
keys1.put(RegExpTT.RUBY_NAMED_GROUP, PARENTHS);
keys1.put(RegExpTT.RUBY_QUOTED_NAMED_GROUP, PARENTHS);
keys1.put(RegExpTT.GROUP_BEGIN, PARENTHS);
keys1.put(RegExpTT.GROUP_END, PARENTHS);
@@ -29,6 +29,8 @@ public interface RegExpGroup extends RegExpAtom {
boolean isRubyNamedGroup();
boolean isNamedGroup();
@Nullable
String getGroupName();
}
@@ -56,6 +56,10 @@ public class RegExpGroupImpl extends RegExpElementImpl implements RegExpGroup {
getNode().findChildByType(RegExpTT.RUBY_QUOTED_NAMED_GROUP) != null;
}
public boolean isNamedGroup() {
return getNode().findChildByType(RegExpTT.RUBY_NAMED_GROUP) != null;
}
public String getGroupName() {
if (!isPythonNamedGroup()) {
return null;
@@ -124,14 +124,14 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
public void visitRegExpBackref(final RegExpBackref backref) {
final RegExpGroup group = backref.resolve();
if (group == null) {
final Annotation a = myHolder.createErrorAnnotation(backref, "Unresolved backreference");
final Annotation a = myHolder.createErrorAnnotation(backref, "Unresolved back reference");
if (a != null) {
// IDEA-9381
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
}
else if (PsiTreeUtil.isAncestor(group, backref, true)) {
myHolder.createWarningAnnotation(backref, "Backreference is nested into the capturing group it refers to");
myHolder.createWarningAnnotation(backref, "Back reference is nested into the capturing group it refers to");
}
}
@@ -173,7 +173,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
*/
final RegExpGroup group = groupRef.resolve();
if (group == null) {
final Annotation a = myHolder.createErrorAnnotation(groupRef, "Unresolved backreference");
final Annotation a = myHolder.createErrorAnnotation(groupRef, "Unresolved back reference");
if (a != null) {
// IDEA-9381
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
@@ -22,6 +22,7 @@ import com.intellij.debugger.engine.evaluation.EvaluationContext;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ThreeState;
import com.intellij.xdebugger.frame.XStackFrame;
import com.sun.jdi.InternalException;
@@ -101,9 +102,29 @@ public class CompoundPositionManager extends PositionManagerEx {
return Collections.emptyList();
}
private static int mapToOriginalLine(int line, int[] mapping) {
for (int i = 0; i < mapping.length; i += 2) {
if (mapping[i + 1] == line) {
return mapping[i];
}
}
return -1;
}
@Override
@NotNull
public List<Location> locationsOfLine(@NotNull ReferenceType type, @NotNull SourcePosition position) {
VirtualFile file = position.getFile().getVirtualFile();
if (file != null) {
int[] data = file.getUserData(LINE_NUMBERS_MAPPING_KEY);
if (data != null) {
int line = mapToOriginalLine(position.getLine() + 1, data);
if (line > -1) {
position = SourcePosition.createFromLine(position.getFile(), line - 1);
}
}
}
for (PositionManager positionManager : myPositionManagers) {
try {
return positionManager.locationsOfLine(type, position);
@@ -140,7 +140,7 @@ public class PositionManagerImpl implements PositionManager {
lineNumber = -1;
}
if (psiFile instanceof PsiCompiledElement && lineNumber > -1) {
if (lineNumber > -1) {
VirtualFile file = psiFile.getVirtualFile();
if (file != null) {
int[] data = file.getUserData(LINE_NUMBERS_MAPPING_KEY);
@@ -15,6 +15,7 @@
*/
package com.intellij.debugger.ui.breakpoints;
import com.intellij.debugger.PositionManager;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -81,8 +82,8 @@ public abstract class JavaLineBreakpointTypeBase<P extends JavaBreakpointPropert
}
@Override
public final boolean canPutAt(@NotNull VirtualFile file, final int line, @NotNull Project project) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
public final boolean canPutAt(@NotNull final VirtualFile file, final int line, @NotNull Project project) {
final PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
// JSPX supports jvm debugging, but not in XHTML files
if (psiFile == null || psiFile.getVirtualFile().getFileType() == StdFileTypes.XHTML) {
return false;
@@ -128,6 +129,9 @@ public abstract class JavaLineBreakpointTypeBase<P extends JavaBreakpointPropert
result.set(JavaLineBreakpointType.class);
}
}
else if (file.getUserData(PositionManager.LINE_NUMBERS_MAPPING_KEY) != null) {
result.set(JavaLineBreakpointType.class);
}
}
if (result.isNull()) {
result.set(JavaMethodBreakpointType.class);
@@ -20,6 +20,7 @@ import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
@@ -100,7 +101,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
addInstruction(new ReturnInstruction(false, null));
new LiveVariablesAnalyzer(myCurrentFlow, myFactory).flushDeadVariablesOnStatementFinish();
if (Registry.is("idea.dfa.live.variables.analysis")) {
new LiveVariablesAnalyzer(myCurrentFlow, myFactory).flushDeadVariablesOnStatementFinish();
}
return myCurrentFlow;
}
@@ -222,24 +222,11 @@ public class DataFlowRunner {
protected DfaInstructionState[] acceptInstruction(InstructionVisitor visitor, DfaInstructionState instructionState) {
Instruction instruction = instructionState.getInstruction();
if (instruction instanceof MethodCallInstruction) {
PsiCallExpression anchor = ((MethodCallInstruction)instruction).getCallExpression();
if (anchor instanceof PsiNewExpression) {
PsiAnonymousClass anonymousClass = ((PsiNewExpression)anchor).getAnonymousClass();
if (anonymousClass != null) {
registerNestedClosures(instructionState, anonymousClass);
}
}
}
else if (instruction instanceof LambdaInstruction) {
PsiLambdaExpression lambdaExpression = ((LambdaInstruction)instruction).getLambdaExpression();
registerNestedClosures(instructionState, lambdaExpression);
}
else if (instruction instanceof EmptyInstruction) {
PsiElement anchor = ((EmptyInstruction)instruction).getAnchor();
if (anchor instanceof PsiClass) {
registerNestedClosures(instructionState, (PsiClass)anchor);
}
PsiElement closure = DfaUtil.getClosureInside(instruction);
if (closure instanceof PsiClass) {
registerNestedClosures(instructionState, (PsiClass)closure);
} else if (closure instanceof PsiLambdaExpression) {
registerNestedClosures(instructionState, (PsiLambdaExpression)closure);
}
return instruction.accept(this, instructionState.getMemoryState(), visitor);
@@ -15,9 +15,7 @@
*/
package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInspection.dataFlow.instructions.AssignInstruction;
import com.intellij.codeInspection.dataFlow.instructions.Instruction;
import com.intellij.codeInspection.dataFlow.instructions.PushInstruction;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.openapi.util.MultiValuesMap;
@@ -113,6 +111,26 @@ public class DfaUtil {
return Collections.emptyList();
}
@Nullable
static PsiElement getClosureInside(Instruction instruction) {
if (instruction instanceof MethodCallInstruction) {
PsiCallExpression anchor = ((MethodCallInstruction)instruction).getCallExpression();
if (anchor instanceof PsiNewExpression) {
return ((PsiNewExpression)anchor).getAnonymousClass();
}
}
else if (instruction instanceof LambdaInstruction) {
return ((LambdaInstruction)instruction).getLambdaExpression();
}
else if (instruction instanceof EmptyInstruction) {
PsiElement anchor = ((EmptyInstruction)instruction).getAnchor();
if (anchor instanceof PsiClass) {
return anchor;
}
}
return null;
}
private static class ValuableInstructionVisitor extends StandardInstructionVisitor {
final Map<PsiElement, PlaceResult> myResults = ContainerUtil.newHashMap();
@@ -21,10 +21,11 @@ import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
import com.intellij.psi.PsiReferenceExpression;
import com.intellij.util.PairFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FilteringIterator;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.containers.*;
import com.intellij.util.containers.Queue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,6 +40,26 @@ public class LiveVariablesAnalyzer {
private final Instruction[] myInstructions;
private final MultiMap<Instruction, Instruction> myForwardMap;
private final MultiMap<Instruction, Instruction> myBackwardMap;
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection") private final FactoryMap<PsiElement, List<DfaVariableValue>> myClosureReads = new FactoryMap<PsiElement, List<DfaVariableValue>>() {
@Nullable
@Override
protected List<DfaVariableValue> create(PsiElement closure) {
final Set<DfaVariableValue> result = ContainerUtil.newLinkedHashSet();
closure.accept(new PsiRecursiveElementWalkingVisitor() {
@Override
public void visitElement(PsiElement element) {
if (element instanceof PsiReferenceExpression) {
DfaValue value = myFactory.createValue((PsiReferenceExpression)element);
if (value instanceof DfaVariableValue) {
result.add((DfaVariableValue)value);
}
}
super.visitElement(element);
}
});
return ContainerUtil.newArrayList(result);
}
};
public LiveVariablesAnalyzer(ControlFlow flow, DfaValueFactory factory) {
myFactory = factory;
@@ -96,12 +117,36 @@ public class LiveVariablesAnalyzer {
return result;
}
@Nullable
private static DfaVariableValue getWrittenVariable(Instruction instruction) {
if (instruction instanceof AssignInstruction) {
DfaValue value = ((AssignInstruction)instruction).getAssignedValue();
return value instanceof DfaVariableValue ? (DfaVariableValue)value : null;
}
if (instruction instanceof FlushVariableInstruction) return ((FlushVariableInstruction)instruction).getVariable();
return null;
}
@NotNull
private List<DfaVariableValue> getReadVariables(Instruction instruction) {
if (instruction instanceof PushInstruction && !((PushInstruction)instruction).isReferenceWrite()) {
DfaValue value = ((PushInstruction)instruction).getValue();
if (value instanceof DfaVariableValue) {
return Collections.singletonList((DfaVariableValue)value);
}
} else {
PsiElement closure = DfaUtil.getClosureInside(instruction);
if (closure != null) {
return myClosureReads.get(closure);
}
}
return Collections.emptyList();
}
private boolean isInterestingInstruction(Instruction instruction) {
if (instruction == myInstructions[0]) return true;
if (instruction instanceof PushInstruction) return ((PushInstruction)instruction).getValue() instanceof DfaVariableValue;
if (instruction instanceof AssignInstruction) return ((AssignInstruction)instruction).getAssignedValue() != null;
if (!getReadVariables(instruction).isEmpty() || getWrittenVariable(instruction) != null) return true;
return instruction instanceof FinishElementInstruction ||
instruction instanceof FlushVariableInstruction ||
instruction instanceof GotoInstruction ||
instruction instanceof ConditionalGotoInstruction ||
instruction instanceof ReturnInstruction;
@@ -124,34 +169,24 @@ public class LiveVariablesAnalyzer {
}
}
if (instruction instanceof AssignInstruction) {
DfaValue value = ((AssignInstruction)instruction).getAssignedValue();
if (value instanceof DfaVariableValue) {
liveVars = (BitSet)liveVars.clone();
liveVars.clear(value.getID());
for (DfaVariableValue var : myFactory.getVarFactory().getAllQualifiedBy((DfaVariableValue)value)) {
liveVars.clear(var.getID());
}
DfaVariableValue written = getWrittenVariable(instruction);
if (written != null) {
liveVars = (BitSet)liveVars.clone();
liveVars.clear(written.getID());
for (DfaVariableValue var : myFactory.getVarFactory().getAllQualifiedBy(written)) {
liveVars.clear(var.getID());
}
}
if (instruction instanceof PushInstruction) {
DfaValue value = ((PushInstruction)instruction).getValue();
if (value instanceof DfaVariableValue) {
if (!((PushInstruction)instruction).isReferenceWrite() && !liveVars.get(value.getID())) {
liveVars = (BitSet)liveVars.clone();
} else {
boolean cloned = false;
for (DfaVariableValue value : getReadVariables(instruction)) {
if (!liveVars.get(value.getID())) {
if (!cloned) {
liveVars = (BitSet)liveVars.clone();
cloned = true;
}
liveVars.set(value.getID());
}
}
} else if (instruction instanceof FlushVariableInstruction) {
DfaVariableValue variable = ((FlushVariableInstruction)instruction).getVariable();
if (variable != null) {
liveVars = (BitSet)liveVars.clone();
liveVars.clear(variable.getID());
for (DfaVariableValue var : myFactory.getVarFactory().getAllQualifiedBy(variable)) {
liveVars.clear(var.getID());
}
}
}
return liveVars;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -60,7 +60,7 @@ public class JavaRegExpHost implements RegExpLanguageHost {
@Override
public boolean supportsNamedGroupSyntax(RegExpGroup group) {
if (group.isRubyNamedGroup()) {
if (group.isNamedGroup()) {
final Module module = ModuleUtilCore.findModuleForPsiElement(group);
if (module != null) {
final Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
@@ -0,0 +1,19 @@
import org.jetbrains.annotations.Nullable;
class Foo {
void foo(final @Nullable String s, String s2) {
if (s2 == null) return;
if (s == null) return;
System.out.println(s2);
new Runnable() {
@Override
public void run() {
s.hashCode();
}
}.run();
}
}
@@ -242,6 +242,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testManyContinuesNotComplex() { doTest(); }
public void testFinallyNotComplex() { doTest(); }
public void testFlushFurtherUnusedVariables() { doTest(); }
public void testDontFlushVariablesUsedInClosures() { doTest(); }
public void testVariablesDiverge() { doTest(); }
public void testMergeByNullability() { doTest(); }
@@ -15,19 +15,25 @@
*/
package com.intellij.index;
import com.intellij.codeInsight.CodeInsightTestCase;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.impl.CurrentEditorProvider;
import com.intellij.openapi.command.impl.UndoManagerImpl;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.SkipSlowTestLocally;
@@ -47,7 +53,7 @@ import java.util.*;
* Date: Dec 12, 2007
*/
@SkipSlowTestLocally
public class IndexTest extends IdeaTestCase {
public class IndexTest extends CodeInsightTestCase {
public void testUpdate() throws StorageException, IOException {
final File storageFile = FileUtil.createTempFile("indextest", "storage");
@@ -208,8 +214,7 @@ public class IndexTest extends IdeaTestCase {
VfsUtil.saveText(vFile, "class Foo {}");
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
assertNotNull(facade.findClass("Foo", scope));
assertNotNull(myJavaFacade.findClass("Foo", scope));
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
@@ -218,20 +223,20 @@ public class IndexTest extends IdeaTestCase {
Document document = FileDocumentManager.getInstance().getDocument(vFile);
document.deleteString(0, document.getTextLength());
assertNotNull(facade.findClass("Foo", scope));
assertNotNull(myJavaFacade.findClass("Foo", scope));
psiFile = null;
PlatformTestUtil.tryGcSoftlyReachableObjects();
assertNull(((PsiManagerEx)PsiManager.getInstance(getProject())).getFileManager().getCachedPsiFile(vFile));
PsiClass foo = facade.findClass("Foo", scope);
PsiClass foo = myJavaFacade.findClass("Foo", scope);
assertNotNull(foo);
assertTrue(foo.isValid());
assertEquals("class Foo {}", foo.getText());
assertTrue(foo.isValid());
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertNull(facade.findClass("Foo", scope));
assertNull(myJavaFacade.findClass("Foo", scope));
}
});
}
@@ -244,8 +249,7 @@ public class IndexTest extends IdeaTestCase {
VfsUtil.saveText(vFile, "");
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
assertNull(facade.findClass("Foo", scope));
assertNull(myJavaFacade.findClass("Foo", scope));
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
@@ -259,11 +263,11 @@ public class IndexTest extends IdeaTestCase {
FileDocumentManager.getInstance().saveDocument(document);
assertTrue(count == PsiManager.getInstance(myProject).getModificationTracker().getModificationCount());
assertNull(facade.findClass("Foo", scope));
assertNull(myJavaFacade.findClass("Foo", scope));
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertNotNull(facade.findClass("Foo", scope));
assertNotNull(facade.findClass("Foo", scope).getText());
assertNotNull(myJavaFacade.findClass("Foo", scope));
assertNotNull(myJavaFacade.findClass("Foo", scope).getText());
// if Foo exists now, mod count should be different
assertTrue(count != PsiManager.getInstance(myProject).getModificationTracker().getModificationCount());
}
@@ -303,9 +307,45 @@ public class IndexTest extends IdeaTestCase {
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertEquals(" Foo", file.getText());
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
}
});
}
public void testUndoToFileContentForUnsavedCommittedDocument() throws IOException {
VirtualFile dir = getVirtualFile(createTempDirectory());
PsiTestUtil.addSourceContentToRoots(myModule, dir);
final VirtualFile vFile = createChildData(dir, "Foo.java");
VfsUtil.saveText(vFile, "class Foo {}");
((VirtualFileSystemEntry)vFile).setModificationStamp(0); // as unchanged file
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
assertTrue(document != null && document.getModificationStamp() == 0);
final GlobalSearchScope scope = GlobalSearchScope.projectScope(myProject);
assertNotNull(myJavaFacade.findClass("Foo", scope));
WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
@Override
public void run() {
document.insertString(0, "import Bar;\n");
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertNotNull(myJavaFacade.findClass("Foo", scope));
}
});
final UndoManager undoManager = UndoManager.getInstance(getProject());
final FileEditor selectedEditor = FileEditorManager.getInstance(myProject).openFile(vFile, false)[0];
((UndoManagerImpl)undoManager).setEditorProvider(new CurrentEditorProvider() {
@Override
public FileEditor getCurrentEditor() {
return selectedEditor;
}
});
assertTrue(undoManager.isUndoAvailable(selectedEditor));
FileDocumentManager.getInstance().saveDocument(document);
undoManager.undo(selectedEditor);
assertNotNull(myJavaFacade.findClass("Foo", scope));
}
}
@@ -132,11 +132,11 @@ public class ProjectTreeSortingTest extends BaseProjectViewTestCase {
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(false);
assertTree("-foldersOnTop\n" +
" a.java\n" +
" +b.java\n" +
" c.java\n" +
" a.txt\n" +
" c.txt\n" +
" +b.java\n" +
" +b.txt\n");
" +b.txt\n"+
" c.txt\n");
}
public void testSortByTypeBetweenFilesAndFolders() throws Exception {
@@ -156,11 +156,11 @@ public class ProjectTreeSortingTest extends BaseProjectViewTestCase {
assertTree("-sortByTypeBetweenFilesAndFolders\n" +
" a.java\n" +
" b.java\n" +
" +a.java_folder\n" +
" +b.java_folder\n" +
" a.txt\n" +
" b.txt\n" +
" +a.java_folder\n" +
" +a_folder\n" +
" +b.java_folder\n" +
" +b_folder\n");
}
@@ -1,9 +1,7 @@
package com.intellij.json.formatter;
import com.intellij.formatting.*;
import com.intellij.json.JsonElementTypes;
import com.intellij.json.JsonLanguage;
import com.intellij.json.JsonParserDefinition;
import com.intellij.json.psi.JsonArray;
import com.intellij.json.psi.JsonObject;
import com.intellij.json.psi.JsonProperty;
@@ -23,18 +21,19 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
import static com.intellij.json.JsonParserDefinition.JSON_BRACES;
import static com.intellij.json.JsonParserDefinition.JSON_BRACKETS;
import static com.intellij.json.JsonElementTypes.*;
import static com.intellij.json.JsonParserDefinition.*;
import static com.intellij.json.formatter.JsonCodeStyleSettings.PropertyAlignment.ALIGN_ON_COLON;
import static com.intellij.json.formatter.JsonCodeStyleSettings.PropertyAlignment.ALIGN_ON_VALUE;
import static com.intellij.json.psi.JsonPsiUtil.hasElementType;
/**
* @author Mikhail Golubev
*/
public class JsonBlock implements ASTBlock {
private static final TokenSet OPEN_BRACES = TokenSet.create(JsonElementTypes.L_BRACKET, JsonElementTypes.L_CURLY);
private static final TokenSet CLOSE_BRACES = TokenSet.create(JsonElementTypes.R_BRACKET, JsonElementTypes.R_CURLY);
private static final TokenSet BRACES = TokenSet.orSet(OPEN_BRACES, CLOSE_BRACES);
private static final TokenSet JSON_OPEN_BRACES = TokenSet.create(L_BRACKET, L_CURLY);
private static final TokenSet JSON_CLOSE_BRACES = TokenSet.create(R_BRACKET, R_CURLY);
private static final TokenSet JSON_ALL_BRACES = TokenSet.orSet(JSON_OPEN_BRACES, JSON_CLOSE_BRACES);
private final JsonBlock myParent;
@@ -48,8 +47,6 @@ public class JsonBlock implements ASTBlock {
// lazy initialized on first call to #getSubBlocks()
private List<Block> mySubBlocks = null;
private final Alignment myChildAlignment = Alignment.createAlignment();
private final Alignment myPropertyValueAlignment;
private final Wrap myChildWrap;
@@ -111,28 +108,35 @@ public class JsonBlock implements ASTBlock {
}
private Block makeSubBlock(@NotNull ASTNode childNode) {
final IElementType childNodeType = childNode.getElementType();
Indent indent = Indent.getNoneIndent();
Alignment alignment = null;
Wrap wrap = null;
JsonCodeStyleSettings customSettings = getCustomSettings();
if (isContainer() && childNodeType != JsonElementTypes.COMMA && !BRACES.contains(childNodeType)) {
assert myChildWrap != null && myChildAlignment != null;
wrap = myChildWrap;
alignment = myChildAlignment;
indent = Indent.getNormalIndent();
final JsonCodeStyleSettings customSettings = getCustomSettings();
if (hasElementType(myNode, JSON_CONTAINERS)) {
if (!hasElementType(childNode, COMMA) && !hasElementType(childNode, JSON_ALL_BRACES)) {
assert myChildWrap != null;
wrap = myChildWrap;
indent = Indent.getNormalIndent();
}
else if (hasElementType(childNode, JSON_OPEN_BRACES)) {
if (JsonPsiUtil.isPropertyValue(myPsiElement) && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_VALUE) {
// WEB-13587 Align compound values on opening brace/bracket, not the whole block
assert myParent != null && myParent.myParent != null && myParent.myParent.myPropertyValueAlignment != null;
alignment = myParent.myParent.myPropertyValueAlignment;
}
}
}
// Handle properties alignment
else if (myNode.getElementType() == JsonElementTypes.PROPERTY) {
assert myParent.myNode.getElementType() == JsonElementTypes.OBJECT;
assert myParent.myPropertyValueAlignment != null;
if (childNode.getElementType() == JsonElementTypes.COLON && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_COLON) {
else if (hasElementType(myNode, PROPERTY) ) {
assert myParent != null && myParent.myPropertyValueAlignment != null;
if (hasElementType(childNode, COLON) && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_COLON) {
alignment = myParent.myPropertyValueAlignment;
}
else if (JsonPsiUtil.isPropertyValue(childNode.getPsi()) && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_VALUE) {
alignment = myParent.myPropertyValueAlignment;
if (!hasElementType(childNode, JSON_CONTAINERS)) {
alignment = myParent.myPropertyValueAlignment;
}
}
}
return new JsonBlock(this, childNode, mySettings, alignment, indent, wrap);
@@ -160,17 +164,17 @@ public class JsonBlock implements ASTBlock {
@Override
public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) {
final CommonCodeStyleSettings commonSettings = getCommonSettings();
final IElementType leftChildType = child1 instanceof JsonBlock ? ((JsonBlock)child1).myNode.getElementType() : null;
final IElementType rightChildType = child2 instanceof JsonBlock ? ((JsonBlock)child2).myNode.getElementType() : null;
final ASTNode leftChild = child1 instanceof JsonBlock ? ((JsonBlock)child1).myNode : null;
final ASTNode rightChild = child2 instanceof JsonBlock ? ((JsonBlock)child2).myNode : null;
// This causes braces/brackets to be on their own lines if whole object/array spans several lines.
if (leftChildType != null && rightChildType != null) {
if (JSON_BRACES.contains(leftChildType) ^ JSON_BRACES.contains(rightChildType)) {
if (leftChild != null && rightChild != null) {
if (hasElementType(leftChild, JSON_BRACES) ^ hasElementType(rightChild, JSON_BRACES)) {
final int numSpaces = commonSettings.SPACE_WITHIN_BRACES ? 1 : 0;
return Spacing.createDependentLFSpacing(numSpaces, numSpaces, myNode.getTextRange(),
commonSettings.KEEP_LINE_BREAKS,
commonSettings.KEEP_BLANK_LINES_IN_CODE);
}
else if (JSON_BRACKETS.contains(leftChildType) ^ JSON_BRACKETS.contains(rightChildType)) {
else if (hasElementType(leftChild, JSON_BRACKETS) ^ hasElementType(rightChild, JSON_BRACKETS)) {
final int numSpaces = commonSettings.SPACE_WITHIN_BRACKETS ? 1 : 0;
return Spacing.createDependentLFSpacing(numSpaces, numSpaces, myNode.getTextRange(),
commonSettings.KEEP_LINE_BREAKS,
@@ -183,8 +187,11 @@ public class JsonBlock implements ASTBlock {
@NotNull
@Override
public ChildAttributes getChildAttributes(int newChildIndex) {
if (isContainer()) {
return new ChildAttributes(Indent.getNormalIndent(), myChildAlignment);
if (hasElementType(myNode, JSON_CONTAINERS)) {
// WEB-13675: For some reason including alignment in child attributes causes
// indents to consist solely of spaces when both USE_TABS and SMART_TAB
// options are enabled.
return new ChildAttributes(Indent.getNormalIndent(), null);
}
// Will use continuation indent for cases like { "foo"<caret> }
return new ChildAttributes(null, null);
@@ -192,15 +199,14 @@ public class JsonBlock implements ASTBlock {
@Override
public boolean isIncomplete() {
IElementType nodeType = myNode.getElementType();
ASTNode lastChildNode = myNode.getLastChildNode();
if (nodeType == JsonElementTypes.OBJECT) {
return lastChildNode != null && lastChildNode.getElementType() != JsonElementTypes.R_CURLY;
final ASTNode lastChildNode = myNode.getLastChildNode();
if (hasElementType(myNode, OBJECT)) {
return lastChildNode != null && lastChildNode.getElementType() != R_CURLY;
}
else if (nodeType == JsonElementTypes.ARRAY) {
return lastChildNode != null && lastChildNode.getElementType() != JsonElementTypes.R_BRACKET;
else if (hasElementType(myNode, ARRAY)) {
return lastChildNode != null && lastChildNode.getElementType() != R_BRACKET;
}
else if (myPsiElement instanceof JsonProperty) {
else if (hasElementType(myNode, PROPERTY)) {
return ((JsonProperty)myPsiElement).getValue() == null;
}
return false;
@@ -215,10 +221,6 @@ public class JsonBlock implements ASTBlock {
return node.getElementType() == TokenType.WHITE_SPACE || node.getTextLength() == 0;
}
private boolean isContainer() {
return JsonParserDefinition.JSON_CONTAINERS.contains(myNode.getElementType());
}
private JsonCodeStyleSettings getCustomSettings() {
return mySettings.getCustomSettings(JsonCodeStyleSettings.class);
}
@@ -23,13 +23,16 @@ import java.awt.event.ItemListener;
* @author Mikhail Golubev
*/
public class JsonCodeStylePanel extends CodeStyleAbstractPanel {
public static final String SAMPLE = "{\n" +
" \"longKeyName\": true,\n" +
" \"short\": false,\n" +
"\n" +
" \"group2-longKeyName\": null,\n" +
" \"group2-short\": 42\n" +
"}";
public static final String ALIGNMENT_SAMPLE = "{\n" +
" \"foo\": {\n" +
" \"bar\": true,\n" +
" \"baz\": false\n" +
" },\n" +
" \"quux\": [\n" +
" 1, 2.0, 3e0, 4.0e0\n" +
" ],\n" +
" \"longPropertyName\": null\n" +
"}";
private JComboBox myPropertiesAlignmentCombo;
private JPanel myPreviewPanel;
@@ -59,7 +62,6 @@ public class JsonCodeStylePanel extends CodeStyleAbstractPanel {
}
}
});
}
@Override
@@ -82,7 +84,7 @@ public class JsonCodeStylePanel extends CodeStyleAbstractPanel {
@Nullable
@Override
protected String getPreviewText() {
return SAMPLE;
return ALIGNMENT_SAMPLE;
}
@Override
@@ -5,6 +5,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import static com.intellij.json.JsonParserDefinition.JSON_COMMENTARIES;
@@ -86,4 +87,35 @@ public class JsonPsiUtil {
}
return lastSeen.getPsi();
}
/**
* Check that element type of the given AST node belongs to the token set.
* <p/>
* It slightly less verbose than {@code set.contains(node.getElementType())} and overloaded methods with the same name
* allow check ASTNode/PsiElement against both concrete element types and token sets in uniform way.
*/
public static boolean hasElementType(@NotNull ASTNode node, @NotNull TokenSet set) {
return set.contains(node.getElementType());
}
/**
* @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.TokenSet)
*/
public static boolean hasElementType(@NotNull ASTNode node, IElementType... types) {
return hasElementType(node, TokenSet.create(types));
}
/**
* @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.TokenSet)
*/
public static boolean hasElementType(@NotNull PsiElement element, @NotNull TokenSet set) {
return element.getNode() != null && hasElementType(element.getNode(), set);
}
/**
* @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.IElementType...)
*/
public static boolean hasElementType(@NotNull PsiElement element, IElementType... types) {
return element.getNode() != null && hasElementType(element.getNode(), types);
}
}
@@ -3,6 +3,9 @@ package com.intellij.json;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
/**
@@ -37,4 +40,22 @@ public class JsonEditingTest extends JsonTestCase {
public void testNormalIndentAfterPropertyWithoutComma() {
doTest("\n");
}
// WEB-13675
public void testIndentWithTabsWhenSmartTabEnabled() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myFixture.getProject());
CommonCodeStyleSettings.IndentOptions indentOptions = settings.getCommonSettings(JsonLanguage.INSTANCE).getIndentOptions();
assertNotNull(indentOptions);
CommonCodeStyleSettings.IndentOptions oldSettings = (CommonCodeStyleSettings.IndentOptions)indentOptions.clone();
indentOptions.TAB_SIZE = 4;
indentOptions.INDENT_SIZE = 4;
indentOptions.USE_TAB_CHARACTER = true;
indentOptions.SMART_TABS = true;
try {
doTest("\n\"baz\"");
}
finally {
indentOptions.copyFrom(oldSettings);
}
}
}
@@ -0,0 +1,5 @@
{
"foo": true,
"bar": false,
"baz"
}
@@ -0,0 +1,4 @@
{
"foo": true,
"bar": false,<caret>
}
@@ -1,5 +1,19 @@
{
"a": 1,
"aaa": 2,
"aaaaa": 3
"require-dev": {
"phpunit/phpunit": "~3.7",
"phpunit/phpunit-selenium": "@stable",
"phpunit/phpunit-story": "@stable",
"phpunit/dbunit": "@stable"
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"DreamFactory\\Yii\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-develop": "1.5.x-dev"
}
}
}
@@ -1,5 +1,19 @@
{
"a" : 1,
"aaa" : 2,
"aaaaa": 3
"require-dev" : {
"phpunit/phpunit" : "~3.7",
"phpunit/phpunit-selenium": "@stable",
"phpunit/phpunit-story" : "@stable",
"phpunit/dbunit" : "@stable"
},
"minimum-stability": "dev",
"autoload" : {
"psr-4": {
"DreamFactory\\Yii\\": "src/"
}
},
"extra" : {
"branch-alias": {
"dev-develop": "1.5.x-dev"
}
}
}
@@ -1,5 +1,19 @@
{
"a": 1,
"aaa": 2,
"aaaaa": 3
"require-dev": {
"phpunit/phpunit": "~3.7",
"phpunit/phpunit-selenium": "@stable",
"phpunit/phpunit-story": "@stable",
"phpunit/dbunit": "@stable"
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"DreamFactory\\Yii\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-develop": "1.5.x-dev"
}
}
}
@@ -1,5 +1,19 @@
{
"a": 1,
"aaa": 2,
"aaaaa": 3
"require-dev": {
"phpunit/phpunit": "~3.7",
"phpunit/phpunit-selenium": "@stable",
"phpunit/phpunit-story": "@stable",
"phpunit/dbunit": "@stable"
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"DreamFactory\\Yii\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-develop": "1.5.x-dev"
}
}
}
@@ -1,5 +1,8 @@
[
1, <selection>[2], [true,
false</selection>],
1, <selection>[2],
[
true,
false
]</selection>,
null
]
@@ -1,5 +1,8 @@
[
null,
1, [2], [true,
false]
1, [2],
[
true,
false
]
]
@@ -1,6 +1,10 @@
{
"foo": <selection>false, "bar": 42,
"baz": [1, 2,
3</selection>],
"foo": false,
"bar": <selection>42,
"baz": [
1,
2,
3
]</selection>,
"quux": null
}
@@ -1,6 +1,10 @@
{
"foo": false,
"quux": null,
"foo": false, "bar": 42,
"baz": [1, 2,
3]
"bar": 42,
"baz": [
1,
2,
3
]
}
@@ -35,7 +35,10 @@ public class ComponentSerializationUtil {
public static <S> void loadComponentState(@NotNull PersistentStateComponent<S> configuration, @Nullable Element element) {
if (element != null) {
Class<S> stateClass = getStateClass(configuration.getClass());
configuration.loadState(XmlSerializer.deserialize(element, stateClass));
S state = XmlSerializer.deserialize(element, stateClass);
if (state != null) {
configuration.loadState(state);
}
}
}
}
@@ -318,6 +318,14 @@ public class PsiDirectoryNode extends BasePsiNode<PsiDirectory> implements Navig
return null;
}
@Override
public Comparable getTypeSortKey() {
VirtualFile file = getVirtualFile();
if (file == null) return null;
String extension = file.getExtension();
return extension == null ? null : new PsiFileNode.ExtensionSortKey(extension);
}
@Override
public String getQualifiedNameSortKey() {
final PsiDirectoryFactory factory = PsiDirectoryFactory.getInstance(getProject());
@@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.ui.ScreenUtil;
import com.intellij.util.containers.hash.LinkedHashMap;
@@ -252,15 +253,14 @@ public class DimensionService implements PersistentStateComponent<Element> {
}
JFrame frame = null;
if (project == null) {
final Component owner = IdeFocusManager.findInstance().getFocusOwner();
if (owner != null) {
frame = UIUtil.getParentOfType(JFrame.class, owner);
}
if (frame == null) {
frame = WindowManager.getInstance().findVisibleFrame();
}
} else {
final Component owner = IdeFocusManager.findInstance().getFocusOwner();
if (owner != null) {
frame = UIUtil.getParentOfType(JFrame.class, owner);
}
if (frame == null) {
frame = WindowManager.getInstance().findVisibleFrame();
}
if (project != null && (frame == null || (frame instanceof IdeFrame && project != ((IdeFrame)frame).getProject()))) {
frame = WindowManager.getInstance().getFrame(project);
}
Rectangle screen = new Rectangle(0, 0, 0, 0);
@@ -3,7 +3,7 @@
<grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="503" height="400"/>
<xy x="20" y="20" width="606" height="400"/>
</constraints>
<properties/>
<border type="none"/>
@@ -56,7 +56,7 @@
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Accept &amp;automatically"/>
<text value="Accept non-trusted certificates &amp;automatically"/>
</properties>
</component>
</children>
@@ -771,15 +771,13 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
try {
final FileEditorProvider provider = newProviders[i];
LOG.assertTrue(provider != null, "Provider for file "+file+" is null. All providers: "+Arrays.asList(newProviders));
LOG.assertTrue(provider.accept(myProject, file), "Provider " + provider + " doesn't accept file " + file);
if ((provider instanceof AsyncFileEditorProvider)) {
builders[i] = ApplicationManager.getApplication().runReadAction(new Computable<AsyncFileEditorProvider.Builder>() {
@Override
public AsyncFileEditorProvider.Builder compute() {
return ((AsyncFileEditorProvider)provider).createEditorAsync(myProject, file);
}
});
}
builders[i] = ApplicationManager.getApplication().runReadAction(new Computable<AsyncFileEditorProvider.Builder>() {
@Override
public AsyncFileEditorProvider.Builder compute() {
LOG.assertTrue(provider.accept(myProject, file), "Provider " + provider + " doesn't accept file " + file);
return provider instanceof AsyncFileEditorProvider ? ((AsyncFileEditorProvider)provider).createEditorAsync(myProject, file) : null;
}
});
}
catch (Exception e) {
LOG.error(e);
@@ -747,7 +747,7 @@ public class AbstractPopup implements JBPopup {
Point xy = new Point(aScreenX, aScreenY);
boolean adjustXY = true;
if (myDimensionServiceKey != null) {
if (myUseDimServiceForXYLocation && myDimensionServiceKey != null) {
final Point storedLocation = DimensionService.getInstance().getLocation(myDimensionServiceKey, myProject);
if (storedLocation != null) {
xy = storedLocation;
@@ -436,13 +436,10 @@ public class SwingHelper {
textPane.setContentType(UIUtil.HTML_MIME);
textPane.setEditable(false);
if (background != null) {
textPane.setBackground(background); // e.g. UIUtil.getOptionPaneBackground()
textPane.setBackground(background);
}
else {
textPane.setOpaque(false);
if (UIUtil.isUnderNimbusLookAndFeel()) {
textPane.setBackground(UIUtil.TRANSPARENT_COLOR);
}
}
textPane.setForeground(foreground != null ? foreground : UIUtil.getLabelForeground());
return textPane;
@@ -1009,8 +1009,8 @@ action.ChangeKeymap.text=Keymap
action.ChangeKeymap.description=Change current keymap
action.ChangeLaf.text=Look and Feel
action.ChangeLaf.description=Change current Look\\&Feel
action.ChangeView.text=Screen Mode
action.ChangeView.description=Change screen mode
action.ChangeView.text=View Mode
action.ChangeView.description=Change view mode
action.ChangeInspectionProfile.text=Switch Error Highlighting
action.ChangeInspectionProfile.description=Change current editor inspection profile
action.ChangeCustomizationSchema.text=Switch Customization Scheme
@@ -3,6 +3,8 @@ package org.jetbrains.rpc;
import com.intellij.util.text.StringFactory;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
@@ -29,7 +31,7 @@ public final class ChannelBufferToString {
}
}
public static CharBuffer readIntoCharBuffer(CharBuffer charBuffer, ByteBuf buffer, int byteCount) {
public static CharBuffer readIntoCharBuffer(@Nullable CharBuffer charBuffer, @NotNull ByteBuf buffer, int byteCount) {
CharsetDecoder decoder = CharsetUtil.getDecoder(CharsetUtil.UTF_8);
ByteBuffer in = buffer.nioBuffer(buffer.readerIndex(), byteCount);
if (charBuffer == null) {
@@ -52,4 +54,11 @@ public final class ChannelBufferToString {
buffer.skipBytes(byteCount);
return charBuffer;
}
public static void writeIntAsAscii(int value, @NotNull ByteBuf buffer) {
String string = Integer.toString(value);
for (int i = 0; i < string.length(); i++) {
buffer.writeByte(string.charAt(i));
}
}
}
@@ -0,0 +1,87 @@
package org.jetbrains.rpc;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.io.SimpleChannelInboundHandlerAdapter;
import java.nio.CharBuffer;
public abstract class MessageDecoder extends SimpleChannelInboundHandlerAdapter<ByteBuf> {
protected int contentLength;
protected final StringBuilder builder = new StringBuilder(64);
private CharBuffer chunkedContent;
private int consumedContentByteCount = 0;
protected final int parseContentLength() {
return parseInt(builder, 0, false, 10);
}
@Nullable
protected String doReadContent(@NotNull ByteBuf buffer) {
int required = contentLength - consumedContentByteCount;
String result;
if (buffer.readableBytes() < required) {
if (chunkedContent == null) {
chunkedContent = CharBuffer.allocate(contentLength);
}
int count = buffer.readableBytes();
ChannelBufferToString.readIntoCharBuffer(chunkedContent, buffer, count);
consumedContentByteCount += count;
return null;
}
else if (chunkedContent != null) {
ChannelBufferToString.readIntoCharBuffer(chunkedContent, buffer, required);
result = ChannelBufferToString.charBufferToString(chunkedContent);
chunkedContent = null;
consumedContentByteCount = 0;
return result;
}
else {
// we can produce char sequence CharSequence result = CharsetUtil.UTF_8.decode(buffer.toByteBuffer(buffer.readerIndex(), required));
// but later, in JsonReaderEx, it will be toString in any case, so, in this case, intermediate java.nio.HeapCharBuffer will be created - so, we stay with String
return ChannelBufferToString.readString(buffer, required);
}
}
/**
* Javolution - Java(TM) Solution for Real-Time and Embedded Systems
* Copyright (C) 2006 - Javolution (http://javolution.org/)
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software is
* freely granted, provided that this notice is preserved.
*/
private static int parseInt(final CharSequence value, final int start, final boolean isNegative, final int radix) {
final int end = value.length();
int result = 0; // Accumulates negatively (avoid MIN_VALUE overflow).
int i = start;
for (; i < end; i++) {
char c = value.charAt(i);
int digit = (c <= '9') ? c - '0'
: ((c <= 'Z') && (c >= 'A')) ? c - 'A' + 10
: ((c <= 'z') && (c >= 'a')) ? c - 'a' + 10 : -1;
if ((digit >= 0) && (digit < radix)) {
int newResult = result * radix - digit;
if (newResult > result) {
throw new NumberFormatException("Overflow parsing " + value.subSequence(start, end));
}
result = newResult;
}
else {
break;
}
}
// Requires one valid digit character and checks for opposite overflow.
if ((result == 0) && ((end == 0) || (value.charAt(i - 1) != '0'))) {
throw new NumberFormatException("Invalid integer representation for " + value.subSequence(start, end));
}
if ((result == Integer.MIN_VALUE) && !isNegative) {
throw new NumberFormatException("Overflow parsing " + value.subSequence(start, end));
}
return isNegative ? result : -result;
}
}
@@ -2,15 +2,22 @@ package org.jetbrains.debugger.connection;
import com.intellij.ide.browsers.WebBrowser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.components.JBList;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.socketConnection.ConnectionStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.debugger.Vm;
import javax.swing.*;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
@@ -87,4 +94,46 @@ public abstract class RemoteVmConnection extends VmConnection<Vm> {
}
return callback;
}
@NotNull
public static <T> AsyncResult<T> chooseDebuggee(@NotNull final Collection<T> targets, final int selectedIndex, @NotNull final Function<T, String> itemToString) {
if (targets.size() == 1) {
return AsyncResult.done(ContainerUtil.getFirstItem(targets));
}
final AsyncResult<T> result = new AsyncResult<T>();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
final JBList list = new JBList(targets);
list.setCellRenderer(new ColoredListCellRenderer() {
@Override
protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
//noinspection unchecked
append(itemToString.fun((T)value));
}
});
list.setSelectedIndex(selectedIndex);
JBPopupFactory.getInstance().
createListPopupBuilder(list).
setTitle("Choose Page to debug").
setItemChoosenCallback(new Runnable() {
@Override
public void run() {
@SuppressWarnings("unchecked")
T value = (T)list.getSelectedValue();
if (value == null) {
result.setRejected();
}
else {
result.setDone(value);
}
}
}).
createPopup().showInFocusCenter();
}
});
return result;
}
}
@@ -24,7 +24,6 @@ public abstract class VmConnection<T extends Vm> implements Disposable, BrowserC
protected volatile T vm;
private final ActionCallback opened = new ActionCallback();
private final AtomicBoolean closed = new AtomicBoolean();
public final Vm getVm() {
@@ -665,6 +665,15 @@ public final class JsonReaderEx implements Closeable {
* Returns the next token, a {@link JsonToken#NAME property name}, and consumes it
*/
public String nextName() {
String result = nextNameOrNull();
if (result == null) {
throw createParseError("Expected a name but was " + peek());
}
return result;
}
@Nullable
public String nextNameOrNull() {
int p = peeked;
if (p == PEEKED_NONE) {
p = doPeek();
@@ -680,7 +689,10 @@ public final class JsonReaderEx implements Closeable {
result = nextQuotedValue('"');
}
else {
throw createParseError("Expected a name but was " + peek());
if (p != PEEKED_END_OBJECT && p != PEEKED_END_ARRAY) {
throw createParseError("Expected a name but was " + peek());
}
return null;
}
peeked = PEEKED_NONE;
return result;
@@ -713,6 +725,7 @@ public final class JsonReaderEx implements Closeable {
return in.charAt(offset + index);
}
@NotNull
@Override
public CharSequence subSequence(int start, int end) {
if ((end - start) > length) {
@@ -1153,6 +1166,7 @@ public final class JsonReaderEx implements Closeable {
/**
* Closes this JSON reader and the underlying {@link java.io.Reader}.
*/
@Override
public void close() {
peeked = PEEKED_NONE;
stack[0] = JsonScope.CLOSED;
@@ -1180,11 +1194,7 @@ public final class JsonReaderEx implements Closeable {
push(JsonScope.EMPTY_OBJECT);
count++;
}
else if (p == PEEKED_END_ARRAY) {
stackSize--;
count--;
}
else if (p == PEEKED_END_OBJECT) {
else if (p == PEEKED_END_ARRAY || p == PEEKED_END_OBJECT) {
stackSize--;
count--;
}
@@ -1,7 +1,6 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.jetbrains.jsonProtocol;
import java.lang.annotation.ElementType;
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
@@ -10,6 +10,6 @@
<orderEntry type="library" name="Trove4j" level="project" />
<orderEntry type="library" name="gson" level="project" />
<orderEntry type="module" module-name="protocol-reader-runtime" exported="" />
<orderEntry type="module" module-name="annotations" />
</component>
</module>
</module>
@@ -1,29 +0,0 @@
package org.jetbrains.protocolReader;
class AbsentSubtypeAspect extends SubtypeAspect {
@Override
void writeGetSuperMethodJava(TextOutput out) {
}
@Override
void writeSuperFieldJava(TextOutput out) {
}
@Override
void writeSuperConstructorParamJava(TextOutput out) {
}
@Override
void writeSuperConstructorInitialization(TextOutput out) {
}
@Override
void writeParseMethod(String className, ClassScope scope, TextOutput out) {
}
@Override
public void writeInstantiateCode(String className, TextOutput out) {
out.append("new ").append(className);
}
}
@@ -1,10 +1,11 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.jetbrains.protocolReader;
import java.util.*;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
public class DynamicReader<ROOT> {
final LinkedHashMap<Class<?>, TypeHandler<?>> typeToTypeHandler;
@@ -15,20 +16,20 @@ public class DynamicReader<ROOT> {
root = new ReaderRoot<>(readerRootClass, typeToTypeHandler);
}
public GeneratedCodeMap generateStaticReader(StringBuilder stringBuilder, String packageName, String className,
Collection<GeneratedCodeMap> basePackages) {
final GlobalScope globalScope = new GlobalScope(typeToTypeHandler.values(), basePackages);
@NotNull
public GeneratedCodeMap generateReader(StringBuilder stringBuilder, String packageName, String className,
Collection<GeneratedCodeMap> basePackages) {
GlobalScope globalScope = new GlobalScope(typeToTypeHandler.values(), basePackages);
FileScope fileScope = globalScope.newFileScope(stringBuilder);
final TextOutput out = fileScope.getOutput();
TextOutput out = fileScope.getOutput();
out.append("// Generated source");
out.newLine().append("package ").append(packageName).append(';');
out.newLine().newLine().append("import org.jetbrains.jsonProtocol.*;");
out.newLine().newLine().append("import static org.jetbrains.jsonProtocol.JsonReaders.*;");
out.newLine().newLine().append("public final class ").append(className).space();
out.append(root.getType().isInterface() ? "implements" : "extends").space().append(root.getType().getCanonicalName()).openBlock(
false);
out.append(root.getType().isInterface() ? "implements" : "extends").space().append(root.getType().getCanonicalName()).openBlock(false);
final ClassScope rootClassScope = fileScope.newClassScope();
ClassScope rootClassScope = fileScope.newClassScope();
root.writeStaticMethodJava(rootClassScope);
for (TypeHandler<?> typeHandler : typeToTypeHandler.values()) {
@@ -37,27 +38,31 @@ public class DynamicReader<ROOT> {
out.newLine();
}
boolean isFirst = true;
for (TypeHandler<?> typeHandler : globalScope.getTypeFactories()) {
String name = globalScope.getTypeImplShortName(typeHandler);
if (isFirst) {
isFirst = false;
}
else {
out.newLine();
}
String originName = typeHandler.getTypeClass().getCanonicalName();
out.newLine().append("static final class ").append(name).append(Util.TYPE_FACTORY_NAME_POSTFIX).append(" extends ObjectFactory<");
out.newLine().append("private static final class ").append(globalScope.getTypeImplShortName(typeHandler)).append(Util.TYPE_FACTORY_NAME_POSTFIX).append(" extends ObjectFactory<");
out.append(originName).append('>').openBlock();
out.append("@Override").newLine().append("public ").append(originName).append(" read(").append(Util.JSON_READER_PARAMETER_DEF);
out.append(')').openBlock();
out.append("return ");
typeHandler.writeInstantiateCode(rootClassScope, out);
out.append('(').append(Util.READER_NAME).append(");").closeBlock();
out.append('(').append(Util.READER_NAME).append(", null);").closeBlock();
out.closeBlock();
out.newLine();
}
out.closeBlock();
Map<Class<?>, String> typeToImplClassName = new HashMap<>();
Map<Class<?>, String> typeToImplClassName = new THashMap<>();
for (TypeHandler<?> typeHandler : typeToTypeHandler.values()) {
String shortName = fileScope.getTypeImplShortName(typeHandler);
String fullReference = packageName + "." + className + "." + shortName;
typeToImplClassName.put(typeHandler.getTypeClass(), fullReference);
typeToImplClassName.put(typeHandler.getTypeClass(), packageName + "." + className + "." + fileScope.getTypeImplShortName(typeHandler));
}
return new GeneratedCodeMap(typeToImplClassName);
@@ -1,6 +1,6 @@
package org.jetbrains.protocolReader;
class ExistingSubtypeAspect extends SubtypeAspect {
class ExistingSubtypeAspect {
private SubtypeCaster subtypeCaster;
private final TypeRef<?> jsonSuperClass;
@@ -12,28 +12,23 @@ class ExistingSubtypeAspect extends SubtypeAspect {
this.subtypeCaster = subtypeCaster;
}
@Override
void writeGetSuperMethodJava(TextOutput out) {
out.newLine().append("@Override").newLine().append("public ").append(jsonSuperClass.get().getTypeClass().getCanonicalName() ).append(" getSuper()").openBlock();
out.append("return ").append(Util.BASE_VALUE_PREFIX).semi().closeBlock();
}
@Override
void writeSuperFieldJava(TextOutput out) {
out.newLine().append("private final ").append(jsonSuperClass.get().getTypeClass().getCanonicalName()).append(' ').append(Util.BASE_VALUE_PREFIX).semi().newLine();
}
@Override
void writeSuperConstructorParamJava(TextOutput out) {
out.comma().append(jsonSuperClass.get().getTypeClass().getCanonicalName()).append(' ').append(Util.BASE_VALUE_PREFIX);
}
@Override
void writeSuperConstructorInitialization(TextOutput out) {
out.append("this.").append(Util.BASE_VALUE_PREFIX).append(" = ").append(Util.BASE_VALUE_PREFIX).append(';').newLine().newLine();
}
@Override
void writeParseMethod(String className, ClassScope scope, TextOutput out) {
out.newLine().append("public static ").append(className).space().append("parse").append("(").append(Util.JSON_READER_PARAMETER_DEF).append(')').openBlock();
out.append("return ");
@@ -44,7 +39,6 @@ class ExistingSubtypeAspect extends SubtypeAspect {
out.newLine();
}
@Override
public void writeInstantiateCode(String className, TextOutput out) {
out.append(className).append(".parse");
}
@@ -1,5 +1,6 @@
package org.jetbrains.protocolReader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jsonProtocol.JsonField;
import org.jetbrains.jsonProtocol.JsonNullable;
import org.jetbrains.jsonProtocol.JsonOptionalField;
@@ -28,7 +29,7 @@ class FieldProcessor<T> {
// todo sort by source location
Arrays.sort(methods, new Comparator<Method>() {
@Override
public int compare(Method o1, Method o2) {
public int compare(@NotNull Method o1, @NotNull Method o2) {
return o1.getName().compareTo(o2.getName());
}
});
@@ -120,20 +121,10 @@ class FieldProcessor<T> {
int position = volatileFields.size();
FieldTypeInfo fieldTypeInfo;
if (internalType) {
fieldTypeInfo = new FieldTypeInfo() {
@Override
public void appendValueTypeNameJava(FileScope scope, TextOutput out) {
fieldTypeParser.appendInternalValueTypeName(scope, out);
}
};
fieldTypeInfo = fieldTypeParser::appendInternalValueTypeName;
}
else {
fieldTypeInfo = new FieldTypeInfo() {
@Override
public void appendValueTypeNameJava(FileScope scope, TextOutput out) {
fieldTypeParser.appendFinishedValueTypeName(out);
}
};
fieldTypeInfo = (scope, out) -> fieldTypeParser.appendFinishedValueTypeName(out);
}
VolatileFieldBinding binding = new VolatileFieldBinding(position, fieldTypeInfo);
volatileFields.add(binding);
@@ -2,6 +2,7 @@ package org.jetbrains.protocolReader;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -84,7 +85,7 @@ public class GlobalScope {
// Sort to produce consistent GeneratedCodeMap later.
Collections.sort(list, new Comparator<TypeHandler<?>>() {
@Override
public int compare(TypeHandler<?> o1, TypeHandler<?> o2) {
public int compare(@NotNull TypeHandler<?> o1, @NotNull TypeHandler<?> o2) {
return getName(o1).compareTo(getName(o2));
}
@@ -117,7 +117,10 @@ class InterfaceReader {
}
for (SubtypeCaster subtypeCaster : subtypeCasters) {
subtypeCaster.getSubtypeHandler().getSubtypeSupport().setSubtypeCaster(subtypeCaster);
ExistingSubtypeAspect subtypeSupport = subtypeCaster.getSubtypeHandler().getSubtypeSupport();
if (subtypeSupport != null) {
subtypeSupport.setSubtypeCaster(subtypeCaster);
}
}
return typeToTypeHandler;
@@ -4,19 +4,22 @@
package org.jetbrains.protocolReader;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
abstract class MethodHandler {
abstract void writeMethodImplementationJava(ClassScope classScope, Method m, TextOutput out);
protected static void appendMethodSignatureJava(Method m, Iterable<String> paramNames, TextOutput out) {
protected static void appendMethodSignatureJava(@NotNull Method m, @NotNull List<String> paramNames, @NotNull TextOutput out) {
out.append(m.getName()).append('(');
boolean firstArg = true;
Iterator<String> namesIt = paramNames.iterator();
for (Type arg : m.getGenericParameterTypes()) {
Type[] types = m.getGenericParameterTypes();
for (int i = 0, length = types.length; i < length; i++) {
Type arg = types[i];
if (firstArg) {
firstArg = false;
}
@@ -24,7 +27,7 @@ abstract class MethodHandler {
out.comma();
}
Util.writeJavaTypeName(arg, out);
out.append(' ').append(namesIt.next());
out.space().append(paramNames.get(i));
}
out.append(')');
}
@@ -33,10 +36,10 @@ abstract class MethodHandler {
writeMethodDeclarationJava(out, m, Collections.<String>emptyList());
}
protected static void writeMethodDeclarationJava(TextOutput out, Method m, Iterable<String> paramNames) {
protected static void writeMethodDeclarationJava(@NotNull TextOutput out, @NotNull Method m, @NotNull List<String> paramNames) {
out.append("@Override").newLine().append("public ");
Util.writeJavaTypeName(m.getGenericReturnType(), out);
out.append(' ');
out.space();
appendMethodSignatureJava(m, paramNames, out);
}
}
@@ -43,7 +43,7 @@ class ObjectValueReader<T> extends ValueReader {
refToType.get().writeInstantiateCode(scope.getRootClassScope(), subtyping, out);
out.append('(');
addReaderParameter(subtyping, out);
if (subtyping && refToType.get().getSubtypeSupport() instanceof ExistingSubtypeAspect) {
if (subtyping && refToType.get().getSubtypeSupport() != null) {
out.comma().append("this");
}
out.append(')');
@@ -1,22 +1,30 @@
package org.jetbrains.protocolReader;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
class ReadDelegate {
private static final List<String> STATIC_METHOD_PARAM_NAME_LIST = Collections.singletonList(Util.READER_NAME);
private static final List<String> STATIC_METHOD_PARAM_NAME_LIST2 = Arrays.asList(Util.READER_NAME, "nextName");
private final TypeHandler<?> typeHandler;
private final boolean isList;
ReadDelegate(TypeHandler<?> typeHandler, boolean isList) {
private final List<String> paramNames;
ReadDelegate(@NotNull TypeHandler<?> typeHandler, boolean isList, boolean hasNextNameParam) {
this.typeHandler = typeHandler;
this.isList = isList;
paramNames = hasNextNameParam ? STATIC_METHOD_PARAM_NAME_LIST2 : STATIC_METHOD_PARAM_NAME_LIST;
}
void write(ClassScope scope, Method method, TextOutput out) {
MethodHandler.writeMethodDeclarationJava(out, method, STATIC_METHOD_PARAM_NAME_LIST);
MethodHandler.writeMethodDeclarationJava(out, method, paramNames);
out.openBlock();
out.append("return ");
if (isList) {
@@ -24,7 +32,10 @@ class ReadDelegate {
}
else {
typeHandler.writeInstantiateCode(scope, out);
out.append("(").append(Util.READER_NAME).append(')');
out.append('(').append(Util.READER_NAME);
out.comma().space();
out.append(paramNames.size() == 1 ? "null" : "nextName");
out.append(')');
}
out.semi();
@@ -18,7 +18,7 @@ public class ReaderGenerator {
configuration.getPackageName().replace('.',
File.separatorChar),
configuration.getClassName() + ".java"));
generateImpl(configuration, fileUpdater.builder);
generate(configuration, fileUpdater.builder);
fileUpdater.update();
}
@@ -96,12 +96,7 @@ public class ReaderGenerator {
}
}
return new Params() {
@Override
public String outputDirectory() {
return outputDirParam.getValue();
}
};
return outputDirParam::getValue;
}
private interface ParamListener {
@@ -128,12 +123,12 @@ public class ReaderGenerator {
}
protected static GeneratedCodeMap buildParserMap(GenerateConfiguration configuration) {
return generateImpl(configuration, new StringBuilder());
return generate(configuration, new StringBuilder());
}
private static GeneratedCodeMap generateImpl(GenerateConfiguration configuration, StringBuilder stringBuilder) {
return configuration.getParser().generateStaticReader(stringBuilder,
configuration.getPackageName(), configuration.getClassName(),
configuration.getBasePackagesMap());
private static GeneratedCodeMap generate(GenerateConfiguration configuration, StringBuilder stringBuilder) {
return configuration.getParser().generateReader(stringBuilder,
configuration.getPackageName(), configuration.getClassName(),
configuration.getBasePackagesMap());
}
}
@@ -1,7 +1,8 @@
package org.jetbrains.protocolReader;
import org.jetbrains.io.JsonReaderEx;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.io.JsonReaderEx;
import org.jetbrains.jsonProtocol.JsonParseMethod;
import java.lang.reflect.Method;
@@ -32,7 +33,7 @@ class ReaderRoot<R> {
Method[] methods = clazz.getMethods();
Arrays.sort(methods, new Comparator<Method>() {
@Override
public int compare(Method o1, Method o2) {
public int compare(@NotNull Method o1, @NotNull Method o2) {
return o1.getName().compareTo(o2.getName());
}
});
@@ -68,12 +69,12 @@ class ReaderRoot<R> {
}
Type[] arguments = m.getGenericParameterTypes();
if (arguments.length != 1) {
if (arguments.length > 2) {
throw new JsonProtocolModelParseException("Exactly one argument is expected in " + m);
}
Type argument = arguments[0];
if (argument == JsonReaderEx.class || argument == Object.class) {
methodMap.put(m, new ReadDelegate(typeHandler, isList));
methodMap.put(m, new ReadDelegate(typeHandler, isList, arguments.length != 1));
}
else {
throw new JsonProtocolModelParseException("Unrecognized argument type in " + m);
@@ -1,19 +0,0 @@
package org.jetbrains.protocolReader;
/**
* Encapsulate subtype aspects of the type.
*/
abstract class SubtypeAspect {
abstract void writeSuperFieldJava(TextOutput out);
abstract void writeSuperConstructorParamJava(TextOutput out);
abstract void writeSuperConstructorInitialization(TextOutput out);
abstract void writeParseMethod(String className, ClassScope scope, TextOutput out);
public abstract void writeInstantiateCode(String className, TextOutput out);
abstract void writeGetSuperMethodJava(TextOutput out);
public void setSubtypeCaster(SubtypeCaster subtypeCaster) {
}
}
@@ -1,9 +1,7 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.jetbrains.protocolReader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jsonProtocol.JsonObjectBased;
import java.lang.reflect.Method;
@@ -16,14 +14,13 @@ class TypeHandler<T> {
private final List<VolatileFieldBinding> volatileFields;
/** Method implementation for dynamic proxy. */
private final LinkedHashMap<Method, MethodHandler> methodHandlerMap;
/** Loaders that should read values and save them in field array on parse time. */
private final List<FieldLoader> fieldLoaders;
/** Subtype aspects of the type or null */
private final SubtypeAspect subtypeAspect;
private final ExistingSubtypeAspect subtypeAspect;
private final boolean hasLazyFields;
@@ -37,29 +34,25 @@ class TypeHandler<T> {
this.methodHandlerMap = methodHandlerMap;
this.fieldLoaders = fieldLoaders;
this.hasLazyFields = hasLazyFields;
if (jsonSuperClass == null) {
subtypeAspect = new AbsentSubtypeAspect();
}
else {
subtypeAspect = new ExistingSubtypeAspect(jsonSuperClass);
}
subtypeAspect = jsonSuperClass == null ? null : new ExistingSubtypeAspect(jsonSuperClass);
}
public Class<T> getTypeClass() {
return typeClass;
}
public SubtypeAspect getSubtypeSupport() {
@Nullable
public ExistingSubtypeAspect getSubtypeSupport() {
return subtypeAspect;
}
public void writeInstantiateCode(ClassScope scope, TextOutput out) {
public void writeInstantiateCode(@NotNull ClassScope scope, @NotNull TextOutput out) {
writeInstantiateCode(scope, false, out);
}
public void writeInstantiateCode(ClassScope scope, boolean deferredReading, TextOutput out) {
public void writeInstantiateCode(@NotNull ClassScope scope, boolean deferredReading, @NotNull TextOutput out) {
String className = scope.getTypeImplReference(this);
if (deferredReading) {
if (deferredReading || subtypeAspect == null) {
out.append("new ").append(className);
}
else {
@@ -67,10 +60,10 @@ class TypeHandler<T> {
}
}
public void writeStaticClassJava(FileScope fileScope) {
public void writeStaticClassJava(@NotNull FileScope fileScope) {
TextOutput out = fileScope.getOutput();
String valueImplClassName = fileScope.getTypeImplShortName(this);
out.append("public static final class ").append(valueImplClassName);
out.append("private static final class ").append(valueImplClassName);
out.append(" implements ").append(getTypeClass().getCanonicalName()).openBlock();
@@ -89,12 +82,16 @@ class TypeHandler<T> {
out.newLine();
}
subtypeAspect.writeSuperFieldJava(out);
if (subtypeAspect != null) {
subtypeAspect.writeSuperFieldJava(out);
}
writeConstructorMethod(valueImplClassName, classScope, out);
out.newLine();
subtypeAspect.writeParseMethod(valueImplClassName, classScope, out);
if (subtypeAspect != null) {
subtypeAspect.writeParseMethod(valueImplClassName, classScope, out);
}
for (Map.Entry<Method, MethodHandler> en : methodHandlerMap.entrySet()) {
out.newLine();
@@ -103,7 +100,9 @@ class TypeHandler<T> {
}
writeBaseMethods(out);
subtypeAspect.writeGetSuperMethodJava(out);
if (subtypeAspect != null) {
subtypeAspect.writeGetSuperMethodJava(out);
}
out.indentOut().append('}');
}
@@ -132,27 +131,47 @@ class TypeHandler<T> {
out.closeBlock();
}
private void writeConstructorMethod(String valueImplClassName, ClassScope classScope, TextOutput out) {
out.newLine().append("public ").append(valueImplClassName).append("(").append(Util.JSON_READER_PARAMETER_DEF);
subtypeAspect.writeSuperConstructorParamJava(out);
private void writeConstructorMethod(@NotNull String valueImplClassName, @NotNull ClassScope classScope, @NotNull TextOutput out) {
out.newLine().append(valueImplClassName).append('(').append(Util.JSON_READER_PARAMETER_DEF).comma().append("String name");
if (subtypeAspect != null) {
subtypeAspect.writeSuperConstructorParamJava(out);
}
out.append(')').openBlock();
subtypeAspect.writeSuperConstructorInitialization(out);
if (subtypeAspect != null) {
subtypeAspect.writeSuperConstructorInitialization(out);
}
if (JsonObjectBased.class.isAssignableFrom(typeClass) || hasLazyFields) {
out.append(Util.PENDING_INPUT_READER_NAME).append(" = ").append(Util.READER_NAME).append(".subReader();").newLine();
out.append(Util.PENDING_INPUT_READER_NAME).append(" = ").append(Util.READER_NAME).append(".subReader()").semi().newLine();
}
if (fieldLoaders.isEmpty()) {
out.append(Util.READER_NAME).append(".skipValue()").semi();
}
else {
out.append(Util.READER_NAME).append(".beginObject();");
out.append("if (name == null)").openBlock();
{
out.append("reader.beginObject()").semi();
out.newLine().append("if (reader.hasNext())").openBlock();
{
out.append("name = reader.nextName()").semi();
}
out.closeBlock();
out.newLine().append("else").openBlock();
{
out.append("return").semi();
}
out.closeBlock();
}
out.closeBlock();
out.newLine();
writeReadFields(out, classScope);
// we don't read all data if we have lazy fields, so, we should not check end of stream
//if (!hasLazyFields) {
out.newLine().append(Util.READER_NAME).append(".endObject();");
out.newLine().newLine().append(Util.READER_NAME).append(".endObject()").semi();
//}
}
out.closeBlock();
@@ -166,16 +185,16 @@ class TypeHandler<T> {
out.newLine().append("int i = 0").semi();
}
out.newLine().append("while (reader.hasNext())").openBlock(!hasOnlyOneFieldLoader);
if (!hasOnlyOneFieldLoader) {
out.append("CharSequence name = reader.nextNameAsCharSequence();");
}
out.newLine().append("do").openBlock();
boolean isFirst = true;
String operator = "if";
for (FieldLoader fieldLoader : fieldLoaders) {
if (!isFirst) {
out.newLine();
}
String fieldName = fieldLoader.getFieldName();
out.newLine().append(operator).append(" (").append(hasOnlyOneFieldLoader ? "reader.nextName()" : "name");
out.append(operator).append(" (").append(hasOnlyOneFieldLoader ? "reader.nextName()" : "name");
out.append(".equals(\"").append(fieldName).append("\"))").openBlock();
{
assignField(out, fieldName);
@@ -204,6 +223,7 @@ class TypeHandler<T> {
out.newLine().append("else").openBlock().append("i++").semi().closeBlock();
}
out.closeBlock();
out.newLine().append("while ((name = reader.nextNameOrNull()) != null)").semi();
}
private static TextOutput assignField(TextOutput out, String fieldName) {
@@ -1,5 +1,7 @@
package org.jetbrains.protocolReader;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
@@ -14,12 +16,12 @@ public class Util {
public static final String BASE_VALUE_PREFIX = "baseMessage";
public static final String JSON_READER_CLASS_NAME = "org.jetbrains.io.JsonReaderEx";
public static final String JSON_READER_PARAMETER_DEF = JSON_READER_CLASS_NAME + " " + READER_NAME;
public static final String JSON_READER_PARAMETER_DEF = JSON_READER_CLASS_NAME + ' ' + READER_NAME;
/**
* Generate Java type name of the passed type. Type may be parameterized.
*/
public static void writeJavaTypeName(Type arg, TextOutput out) {
public static void writeJavaTypeName(@NotNull Type arg, @NotNull TextOutput out) {
if (arg instanceof Class) {
out.append(((Class<?>)arg).getCanonicalName());
}
@@ -281,6 +281,9 @@ ide.dfa.time.limit.online.description=Time limit (in milliseconds) that is allow
ide.dfa.time.limit.offline=5000
ide.dfa.time.limit.offline.description=Time limit (in milliseconds) that is allowed to analyze data flow for one method in Analyze | Inspect Code...
idea.dfa.live.variables.analysis=true
idea.dfa.live.variables.analysis.description=Whether to flush dead variables when they're not needed when performing data flow analysis
ide.ignore.call.result.inspection.honor.inferred.pure=false
ide.ignore.call.result.inspection.honor.inferred.pure.description=Whether inferred @Contract(pure=true) annotations should be taken into account in ''Result of method call ignored'' inspection
@@ -8,7 +8,6 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.NotNullFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.vcs.log.*;
@@ -75,24 +74,32 @@ public class GraphTableModel extends AbstractTableModel {
List<GraphCommit<Integer>> commits = myDataPack.getPermanentGraph().getAllCommits();
for (int i = 0; i < 100 && i < commits.size(); i++) {
GraphCommit<Integer> commit = commits.get(i);
sb.append(myDataHolder.getHash(commit.getId()) + "\n");
sb.append(String.format("%s -> %s\n", myDataHolder.getHash(commit.getId()).toShortString(), getParents(commit)));
}
sb.append("\nALL REFS:\n");
printRefs(sb, myDataHolder.getHashMap().asIndexGetter(), myDataPack.getRefsModel().getAllRefsByRoot());
printRefs(sb, myDataPack.getRefsModel().getAllRefsByRoot());
return sb.toString();
}
private static void printRefs(@NotNull StringBuilder sb,
@NotNull final NotNullFunction<Hash, Integer> indexGetter,
@NotNull Map<VirtualFile, Set<VcsRef>> refs) {
@NotNull
private String getParents(@NotNull GraphCommit<Integer> commit) {
return StringUtil.join(commit.getParents(), new Function<Integer, String>() {
@Override
public String fun(Integer integer) {
return myDataHolder.getHash(integer).toShortString();
}
}, ", ");
}
private static void printRefs(@NotNull StringBuilder sb, @NotNull Map<VirtualFile, Set<VcsRef>> refs) {
for (Map.Entry<VirtualFile, Set<VcsRef>> entry : refs.entrySet()) {
sb.append(entry.getKey().getName() + ":\n");
sb.append("\n\n" + entry.getKey().getName() + ":\n");
sb.append(StringUtil.join(entry.getValue(), new Function<VcsRef, String>() {
@Override
public String fun(@NotNull VcsRef ref) {
return ref.getName() + "(" + indexGetter.fun(ref.getCommitHash()) + ")";
return ref.getName() + " : " + ref.getCommitHash().toShortString();
}
}, ","));
}, "\n"));
}
}
@@ -121,6 +121,7 @@ public class XFramesView extends XDebugView {
XDebugSession session = getSession(e);
if (session != null) {
mySelectedFrameIndex = 0;
myRefresh = false;
updateFrames((XExecutionStack)item, session);
}
}
@@ -305,7 +306,7 @@ public class XFramesView extends XDebugView {
Object selected = myFramesList.getSelectedValue();
if (selected instanceof XStackFrame) {
if (session != null) {
if (force || !myRefresh) {
if (force || (!myRefresh && session.getCurrentStackFrame() != selected)) {
session.setCurrentStackFrame(mySelectedStack, (XStackFrame)selected, mySelectedFrameIndex == 0);
}
}
@@ -182,7 +182,7 @@ class GitPushTargetPanel extends PushTargetPanel<GitPushTarget> {
@Override
public void fireOnChange() {
if (myError == null) {
if (myError != null) {
return;
}
String remoteName = myRemoteLabel.getText();
@@ -82,6 +82,7 @@ public class ControlFlowGraph implements CodeConstants {
}
public String toString() {
if (blocks == null) return "Empty";
String new_line_separator = DecompilerContext.getNewLineSeparator();
@@ -54,6 +54,8 @@
description="Refresh current task"/>
<action id="WatchInputAction" class="com.jetbrains.python.edu.actions.StudyEditInputAction" text="WatchInputAction"
description="watch input"/>
<action id="ShowHintAction" class="com.jetbrains.python.edu.actions.StudyShowHintAction" text="Show hint"
description="Show hint"/>
<action id="StudyRunAction" class="com.jetbrains.python.edu.actions.StudyRunAction" text="StudyRunAction" description="run your code"/>
<action id="WelcomeScreen.PythonIntro" class="com.jetbrains.python.edu.actions.StudyIntroductionCourseAction" icon="StudyIcons.EducationalProjectType">
<add-to-group group-id="WelcomeScreen.QuickStart" anchor="first"/>
@@ -28,7 +28,10 @@ public class StudyInstructionPainter extends EditorEmptyTextPainter {
painter.appendLine("PyCharm Educational Edition").underlined(new JBColor(Gray._150, Gray._180));
painter.appendLine("Navigate to the next task window with Ctrl + Enter").smaller().withBullet();
painter.appendLine("Navigate between task windows with Ctrl + < and Ctrl + >").smaller().withBullet();
painter.appendLine("Navigate between task windows with Ctrl + Shift + < and Ctrl + Shift + >").smaller().withBullet();
painter.appendLine("Navigate between tasks with Ctrl + < and Ctrl + >").smaller().withBullet();
painter.appendLine("Reset current task file with Ctrl + Shift + X").smaller().withBullet();
painter.appendLine("Check task with Alt + Ctrl + Enter").smaller().withBullet();
painter.appendLine("Get hint for the task window using Ctrl + 7").smaller().withBullet();
painter.appendLine("To see your progress open the 'Course Description' panel").smaller().withBullet();
painter.draw(g, new PairFunction<Integer, Integer, Couple<Integer>>() {
@@ -20,9 +20,7 @@ import com.intellij.openapi.vfs.VirtualFileEvent;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.wm.*;
import com.intellij.util.xmlb.XmlSerializer;
import com.jetbrains.python.edu.actions.StudyNextWindowAction;
import com.jetbrains.python.edu.actions.StudyPrevWindowAction;
import com.jetbrains.python.edu.actions.StudyShowHintAction;
import com.jetbrains.python.edu.actions.*;
import com.jetbrains.python.edu.course.Course;
import com.jetbrains.python.edu.course.Lesson;
import com.jetbrains.python.edu.course.Task;
@@ -155,6 +153,10 @@ public class StudyTaskManager implements ProjectComponent, PersistentStateCompon
addShortcut(StudyPrevWindowAction.SHORTCUT, StudyPrevWindowAction.ACTION_ID);
addShortcut(StudyShowHintAction.SHORTCUT, StudyShowHintAction.ACTION_ID);
addShortcut(StudyNextWindowAction.SHORTCUT2, StudyNextWindowAction.ACTION_ID);
addShortcut(StudyCheckAction.SHORTCUT, StudyCheckAction.ACTION_ID);
addShortcut(StudyNextStudyTaskAction.SHORTCUT, StudyNextStudyTaskAction.ACTION_ID);
addShortcut(StudyPreviousStudyTaskAction.SHORTCUT, StudyPreviousStudyTaskAction.ACTION_ID);
addShortcut(StudyRefreshTaskFileAction.SHORTCUT, StudyRefreshTaskFileAction.ACTION_ID);
}
}
});
@@ -41,6 +41,8 @@ public class StudyCheckAction extends DumbAwareAction {
private static final Logger LOG = Logger.getInstance(StudyCheckAction.class.getName());
private static final String ANSWERS_POSTFIX = "_answers.py";
public static final String ACTION_ID = "CheckAction";
public static final String SHORTCUT = "ctrl alt pressed ENTER";
private static void flushWindows(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
@@ -8,6 +8,9 @@ import javax.swing.*;
public class StudyNextStudyTaskAction extends StudyTaskNavigationAction {
public static final String ACTION_ID = "NextTaskAction";
public static final String SHORTCUT = "ctrl pressed PERIOD";
@Override
protected JButton getButton(@NotNull final StudyEditor selectedStudyEditor) {
return selectedStudyEditor.getNextTaskButton();
@@ -12,7 +12,7 @@ import java.util.List;
*/
public class StudyNextWindowAction extends StudyWindowNavigationAction {
public static final String ACTION_ID = "NextWindow";
public static final String SHORTCUT = "ctrl pressed PERIOD";
public static final String SHORTCUT = "ctrl shift pressed PERIOD";
public static final String SHORTCUT2 = "ctrl pressed ENTER";
public StudyNextWindowAction() {
@@ -14,7 +14,7 @@ import java.util.List;
*/
public class StudyPrevWindowAction extends StudyWindowNavigationAction {
public static final String ACTION_ID = "PrevWindowAction";
public static final String SHORTCUT = "ctrl pressed COMMA";
public static final String SHORTCUT = "ctrl shift pressed COMMA";
public StudyPrevWindowAction() {
super("PrevWindowAction", "Select previous window", StudyIcons.Prev);
@@ -9,6 +9,8 @@ import javax.swing.*;
public class StudyPreviousStudyTaskAction extends StudyTaskNavigationAction {
public static final String ACTION_ID = "PreviousTaskAction";
public static final String SHORTCUT = "ctrl pressed COMMA";
@Override
protected JButton getButton(@NotNull final StudyEditor selectedStudyEditor) {
return selectedStudyEditor.getPrevTaskButton();
@@ -28,6 +28,8 @@ import java.io.*;
public class StudyRefreshTaskFileAction extends DumbAwareAction {
private static final Logger LOG = Logger.getInstance(StudyRefreshTaskFileAction.class.getName());
public static final String ACTION_ID = "RefreshTaskAction";
public static final String SHORTCUT = "ctrl shift pressed X";
public static void refresh(final Project project) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -66,7 +66,6 @@ public class StudyEditor implements TextEditor {
private JButton myRefreshButton;
private static final Map<Document, StudyDocumentListener> myDocumentListeners = new HashMap<Document, StudyDocumentListener>();
private final Project myProject;
private JButton myShowHintButton;
public JButton getCheckButton() {
return myCheckButton;
@@ -193,11 +192,11 @@ public class StudyEditor implements TextEditor {
}
private void initializeButtons(@NotNull final JPanel taskActionsPanel, @NotNull final TaskFile taskFile) {
myCheckButton = addButton(taskActionsPanel, "Check task", StudyIcons.Resolve);
myPrevTaskButton = addButton(taskActionsPanel, "Prev Task", StudyIcons.Prev);
myNextTaskButton = addButton(taskActionsPanel, "Next Task", AllIcons.Actions.Forward);
myRefreshButton = addButton(taskActionsPanel, "Start task again", AllIcons.Actions.Refresh);
myShowHintButton = addButton(taskActionsPanel, "Show hint", StudyIcons.ShowHint);
myCheckButton = addButton(taskActionsPanel, "Check task (Ctrl + Alt + Enter)", StudyIcons.Resolve);
myPrevTaskButton = addButton(taskActionsPanel, "Previous task (Ctrl + &lt;)", StudyIcons.Prev);
myNextTaskButton = addButton(taskActionsPanel, "Next task (Ctrl + >)", AllIcons.Actions.Forward);
myRefreshButton = addButton(taskActionsPanel, "Reset task file (Ctrl + Shift + X)", AllIcons.Actions.Refresh);
JButton myShowHintButton = addButton(taskActionsPanel, "Show hint for task window (Ctrl + 7)", StudyIcons.ShowHint);
if (!taskFile.getTask().getUserTests().isEmpty()) {
JButton runButton = addButton(taskActionsPanel, "Run", AllIcons.General.Run);
runButton.addActionListener(new ActionListener() {
@@ -219,7 +219,6 @@ public class XmlElementDescriptorImpl extends XsdEnumerationDescriptor<XmlTag>
if (type instanceof ComplexTypeDescriptor) {
final ComplexTypeDescriptor descriptor = (ComplexTypeDescriptor)type;
String contextNs;
PsiFile containingFile = context != null ? context.getContainingFile():null;
if (context != null && !containingFile.isPhysical()) {
@@ -227,10 +226,11 @@ public class XmlElementDescriptorImpl extends XsdEnumerationDescriptor<XmlTag>
//context = context.getParentTag();
}
String contextNs;
if (context != null &&
( descriptor.canContainTag(context.getLocalName(), contextNs = context.getNamespace(), context ) &&
(!contextNs.equals(getNamespace()) || descriptor.hasAnyInContentModel())
) ) {
descriptor.canContainTag(context.getLocalName(), contextNs = context.getNamespace(), context) &&
(!contextNs.equals(getNamespace()) || descriptor.hasAnyInContentModel()) &&
containingFile instanceof XmlFile) { // JSXmlLiteralExpressionImpl is crazy
final XmlNSDescriptor nsDescriptor = getNSDescriptor();
if (nsDescriptor != null) {