Merge remote-tracking branch 'origin/master'

This commit is contained in:
jamesbrain
2015-10-14 00:41:04 +03:00
12 changed files with 181 additions and 174 deletions
+23 -51
View File
@@ -128,6 +128,7 @@
<option name="BACKGROUND" value="404040" />
</value>
</option>
<option name="CONSOLE_RANGE_TO_EXECUTE" baseAttributes="INJECTED_LANGUAGE_FRAGMENT" />
<option name="CONSOLE_RED_BRIGHT_OUTPUT">
<value>
<option name="FOREGROUND" value="eb6f6f" />
@@ -511,6 +512,7 @@
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="GROOVY_KEYWORD" baseAttributes="JAVA_KEYWORD" />
<option name="GString">
<value>
<option name="FOREGROUND" value="99cc00" />
@@ -561,7 +563,7 @@
</option>
<option name="IDENTIFIER_UNDER_CARET_ATTRIBUTES">
<value>
<option name="BACKGROUND" value="e4e4ff" />
<option name="BACKGROUND" value="46464d" />
<option name="ERROR_STRIPE_COLOR" value="ccccff" />
</value>
</option>
@@ -768,6 +770,19 @@
<option name="FOREGROUND" value="9dd4de" />
</value>
</option>
<option name="KOTLIN_ANNOTATION">
<value>
<option name="FOREGROUND" value="7a8fd9" />
</value>
</option>
<option name="KOTLIN_PROPERTY_WITH_BACKING_FIELD">
<value />
</option>
<option name="KOTLIN_SMART_CAST_VALUE">
<value>
<option name="BACKGROUND" value="485748" />
</value>
</option>
<option name="Keyword">
<value>
<option name="FOREGROUND" value="d2ac67" />
@@ -1160,60 +1175,17 @@
<option name="EFFECT_COLOR" value="a9b7c6" />
</value>
</option>
<option name="SQL_COLUMN">
<value>
<option name="FOREGROUND" value="cc9900" />
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="SQL_DATABASE_OBJECT">
<value>
<option name="FOREGROUND" value="3fa7d4" />
</value>
</option>
<option name="SQL_KEYWORD">
<value>
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="SQL_LOCAL_ALIAS">
<value>
<option name="FOREGROUND" value="c0c0c0" />
</value>
</option>
<option name="SQL_PARAMETER">
<value>
<option name="FOREGROUND" value="6699ff" />
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="SQL_PROCEDURE">
<value>
<option name="FOREGROUND" value="cacc" />
<option name="FONT_TYPE" value="2" />
</value>
</option>
<option name="SQL_STRING">
<value>
<option name="FOREGROUND" value="85cd00" />
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="SQL_SYNTHETIC_ENTITY">
<value>
<option name="FOREGROUND" value="ffff00" />
</value>
</option>
<option name="SQL_TABLE">
<value>
<option name="FOREGROUND" value="ffffff" />
</value>
</option>
<option name="STATIC_FIELD_ATTRIBUTES">
<value>
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="STATIC_FINAL_FIELD_ATTRIBUTES">
<value>
<option name="FOREGROUND" value="c257d2" />
<option name="FONT_TYPE" value="3" />
</value>
</option>
<option name="Static field">
<value>
<option name="FOREGROUND" value="c0c0c0" />
@@ -1280,7 +1252,7 @@
</option>
<option name="WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES">
<value>
<option name="BACKGROUND" value="ffe4ff" />
<option name="BACKGROUND" value="4d444d" />
<option name="ERROR_STRIPE_COLOR" value="ffcdff" />
</value>
</option>
@@ -67,7 +67,7 @@ public class LogicalPosition implements Comparable<LogicalPosition> {
* Number of virtual soft wrap introduced lines on a current logical line before the visual position that corresponds
* to the current logical position.
* <p>
* Instead of directly using this value, EditorUtil.getSoftWrapCountAfterLogicalLineStart(LogicalPosition) method can be used,
* Instead of directly using this value, EditorUtil.getSoftWrapCountAfterLineStart(Editor, LogicalPosition) method can be used,
* it will work regardless of whether current <code>LogicalPosition</code> instance is {@link #visualPositionAware}.
*
* @see #visualPositionAware
@@ -345,17 +345,15 @@ public class FormatProcessor {
}
/**
* Decides whether applying formatter changes should be applied incrementally one-by-one or merge result should be
* constructed locally and the whole document text should be replaced. Performs such single bulk change if necessary.
* Performs formatter changes in a series of blocks, for each block a new contents of document is calculated
* and whole document is replaced in one operation.
*
* @param blocksToModify changes introduced by formatter
* @param model current formatting model
* @param indentOption indent options to use
* @return <code>true</code> if given changes are applied to the document (i.e. no further processing is required);
* <code>false</code> otherwise
*/
@SuppressWarnings({"deprecation"})
private boolean applyChangesAtRewriteMode(@NotNull final List<LeafBlockWrapper> blocksToModify,
private void applyChangesAtRewriteMode(@NotNull final List<LeafBlockWrapper> blocksToModify,
@NotNull final FormattingModel model,
@NotNull CommonCodeStyleSettings.IndentOptions indentOption)
{
@@ -363,33 +361,39 @@ public class FormatProcessor {
Document document = documentModel.getDocument();
CaretOffsetUpdater caretOffsetUpdater = new CaretOffsetUpdater(document);
List<TextChange> changes = new ArrayList<TextChange>();
int shift = 0;
int currentIterationShift = 0;
for (LeafBlockWrapper block : blocksToModify) {
WhiteSpace whiteSpace = block.getWhiteSpace();
CharSequence newWs = documentModel.adjustWhiteSpaceIfNecessary(
whiteSpace.generateWhiteSpace(getIndentOptionsToUse(block, indentOption)), whiteSpace.getStartOffset(),
whiteSpace.getEndOffset(), block.getNode(), false
);
if (changes.size() > 10000) {
caretOffsetUpdater.update(changes);
CharSequence mergeResult = BulkChangesMerger.INSTANCE.mergeToCharSequence(document.getChars(), document.getTextLength(), changes);
document.replaceString(0, document.getTextLength(), mergeResult);
shift += currentIterationShift;
currentIterationShift = 0;
changes.clear();
if (document instanceof DocumentEx) ((DocumentEx)document).setInBulkUpdate(true);
try {
List<TextChange> changes = new ArrayList<TextChange>();
int shift = 0;
int currentIterationShift = 0;
for (LeafBlockWrapper block : blocksToModify) {
WhiteSpace whiteSpace = block.getWhiteSpace();
CharSequence newWs = documentModel.adjustWhiteSpaceIfNecessary(
whiteSpace.generateWhiteSpace(getIndentOptionsToUse(block, indentOption)), whiteSpace.getStartOffset(),
whiteSpace.getEndOffset(), block.getNode(), false
);
if (changes.size() > 10000) {
caretOffsetUpdater.update(changes);
CharSequence mergeResult = BulkChangesMerger.INSTANCE.mergeToCharSequence(document.getChars(), document.getTextLength(), changes);
document.replaceString(0, document.getTextLength(), mergeResult);
shift += currentIterationShift;
currentIterationShift = 0;
changes.clear();
}
TextChangeImpl change = new TextChangeImpl(newWs, whiteSpace.getStartOffset() + shift, whiteSpace.getEndOffset() + shift);
currentIterationShift += change.getDiff();
changes.add(change);
}
TextChangeImpl change = new TextChangeImpl(newWs, whiteSpace.getStartOffset() + shift, whiteSpace.getEndOffset() + shift);
currentIterationShift += change.getDiff();
changes.add(change);
caretOffsetUpdater.update(changes);
CharSequence mergeResult = BulkChangesMerger.INSTANCE.mergeToCharSequence(document.getChars(), document.getTextLength(), changes);
document.replaceString(0, document.getTextLength(), mergeResult);
}
caretOffsetUpdater.update(changes);
CharSequence mergeResult = BulkChangesMerger.INSTANCE.mergeToCharSequence(document.getChars(), document.getTextLength(), changes);
document.replaceString(0, document.getTextLength(), mergeResult);
finally {
if (document instanceof DocumentEx) ((DocumentEx)document).setInBulkUpdate(false);
}
caretOffsetUpdater.restoreCaretLocations();
cleanupBlocks(blocksToModify);
return true;
}
private static void cleanupBlocks(List<LeafBlockWrapper> blocks) {
@@ -1472,17 +1476,17 @@ public class FormatProcessor {
myProgressCallback.beforeApplyingFormatChanges(myBlocksToModify);
final int blocksToModifyCount = myBlocksToModify.size();
final boolean bulkReformat = blocksToModifyCount > 50;
DocumentEx updatedDocument = bulkReformat ? getAffectedDocument(myModel) : null;
if (updatedDocument != null) {
updatedDocument.setInBulkUpdate(true);
myResetBulkUpdateState = true;
}
if (blocksToModifyCount > BULK_REPLACE_OPTIMIZATION_CRITERIA
&& applyChangesAtRewriteMode(myBlocksToModify, myModel, myDefaultIndentOption))
{
if (blocksToModifyCount > BULK_REPLACE_OPTIMIZATION_CRITERIA) {
applyChangesAtRewriteMode(myBlocksToModify, myModel, myDefaultIndentOption);
setDone(true);
}
else if (blocksToModifyCount > 50) {
DocumentEx updatedDocument = getAffectedDocument(myModel);
if (updatedDocument != null) {
updatedDocument.setInBulkUpdate(true);
myResetBulkUpdateState = true;
}
}
}
@Override
@@ -19,6 +19,7 @@ import com.intellij.CommonBundle;
import com.intellij.ide.WelcomeWizardUtil;
import com.intellij.ide.ui.LafManager;
import com.intellij.ide.ui.laf.IntelliJLaf;
import com.intellij.ide.ui.laf.LafManagerImpl;
import com.intellij.ide.ui.laf.darcula.DarculaLaf;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.OptionsBundle;
@@ -43,7 +44,7 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
public ThemeInfo(String name, String previewFileName, String laf) {
this.name = name;
this.previewFileName = previewFileName;
this.previewFileName = SystemInfo.isMac && "IntelliJ".equals(previewFileName) ? "Aqua" : previewFileName;
this.laf = laf;
}
@@ -130,7 +131,7 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
protected void initThemes(Collection<ThemeInfo> result) {
if (SystemInfo.isMac) {
result.add(AQUA);
result.add(LafManagerImpl.useIntelliJInsteadOfAqua() ? INTELLIJ : AQUA);
result.add(DARCULA);
}
else if (SystemInfo.isWindows) {
@@ -124,6 +124,9 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo
ourLafClassesAliases.put("idea.dark.laf.classname", DarculaLookAndFeelInfo.CLASS_NAME);
}
public static boolean useIntelliJInsteadOfAqua() {
return Registry.is("ide.mac.yosemite.laf") && isIntelliJLafEnabled() && SystemInfo.isJavaVersionAtLeast("1.8") && SystemInfo.isMacOSYosemite;
}
/**
* Invoked via reflection.
*/
@@ -133,7 +136,7 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo
List<UIManager.LookAndFeelInfo> lafList = ContainerUtil.newArrayList();
if (SystemInfo.isMac) {
if (Registry.is("ide.mac.yosemite.laf") && isIntelliJLafEnabled() && SystemInfo.isJavaVersionAtLeast("1.8") && SystemInfo.isMacOSYosemite) {
if (useIntelliJInsteadOfAqua()) {
lafList.add(new UIManager.LookAndFeelInfo("Default", IntelliJLaf.class.getName()));
} else {
lafList.add(new UIManager.LookAndFeelInfo("Default", UIManager.getSystemLookAndFeelClassName()));
@@ -320,7 +323,7 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo
}
final String systemLafClassName = UIManager.getSystemLookAndFeelClassName();
if (SystemInfo.isMac) {
String className = Registry.is("ide.mac.yosemite.laf") ? IntelliJLaf.class.getName() : systemLafClassName;
String className = useIntelliJInsteadOfAqua() ? IntelliJLaf.class.getName() : systemLafClassName;
UIManager.LookAndFeelInfo laf = findLaf(className);
LOG.assertTrue(laf != null, "Could not find look and feel: " + className);
return laf;
@@ -56,7 +56,7 @@ public class TextEndWithSelectionAction extends TextComponentEditorAction {
}
int selectionStart = caret.getLeadSelectionOffset();
if (editor instanceof EditorImpl && ((EditorImpl)editor).myUseNewRendering) {
editor.getCaretModel().moveToLogicalPosition(editor.offsetToLogicalPosition(endOffset).leanForward(true));
caret.moveToLogicalPosition(editor.offsetToLogicalPosition(endOffset).leanForward(true));
}
else {
caret.moveToOffset(endOffset);
@@ -84,17 +84,11 @@ class LineLayout {
private static List<BidiRun> createFragments(@NotNull EditorView view, int lineStartOffset, int lineEndOffset, boolean skipBidiLayout) {
if (lineEndOffset <= lineStartOffset) return Collections.emptyList();
if (skipBidiLayout) return Collections.singletonList(new BidiRun(lineEndOffset - lineStartOffset));
EditorImpl editor = view.getEditor();
List<BidiRun> runs;
if (skipBidiLayout) {
runs = Collections.singletonList(new BidiRun((byte)0, 0, lineEndOffset - lineStartOffset));
}
else {
CharSequence text = editor.getDocument().getImmutableCharSequence().subSequence(lineStartOffset, lineEndOffset);
char[] chars = CharArrayUtil.fromSequence(text);
runs = createRuns(editor, chars, lineStartOffset);
}
return runs;
CharSequence text = editor.getDocument().getImmutableCharSequence().subSequence(lineStartOffset, lineEndOffset);
char[] chars = CharArrayUtil.fromSequence(text);
return createRuns(editor, chars, lineStartOffset);
}
private static List<BidiRun> createFragments(@NotNull EditorView view, @NotNull CharSequence text,
@@ -115,7 +109,9 @@ class LineLayout {
private static List<BidiRun> createRuns(EditorImpl editor, char[] text, int startOffsetInEditor) {
int textLength = text.length;
if (editor.myDisableRtl) return Collections.singletonList(new BidiRun((byte)0, 0, textLength));
if (editor.myDisableRtl || !Bidi.requiresBidi(text, 0, textLength)) {
return Collections.singletonList(new BidiRun(textLength));
}
List<BidiRun> runs = new ArrayList<BidiRun>();
if (startOffsetInEditor >= 0) {
// running bidi algorithm separately for text fragments corresponding to different lexer tokens
@@ -324,6 +320,10 @@ class LineLayout {
private final int endOffset;
private Chunk[] chunks; // in logical order
private BidiRun(int length) {
this((byte)0, 0, length);
}
private BidiRun(byte level, int startOffset, int endOffset) {
this.level = level;
this.startOffset = startOffset;
@@ -27,7 +27,6 @@ import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.testFramework.EditorTestUtil;
import com.intellij.testFramework.TestFileType;
import gnu.trove.TIntHashSet;
import gnu.trove.TIntProcedure;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@@ -56,12 +55,16 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
@Override
protected void tearDown() throws Exception {
if (myEditor != null) {
EditorSettings settings = myEditor.getSettings();
settings.setUseSoftWraps(false);
settings.setSmartHome(mySmartHome);
try {
if (myEditor != null) {
EditorSettings settings = myEditor.getSettings();
settings.setUseSoftWraps(false);
settings.setSmartHome(mySmartHome);
}
}
finally {
super.tearDown();
}
super.tearDown();
}
public void testSoftWrapAdditionOnTyping() throws Exception {
@@ -236,12 +239,9 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
type('2');
final TIntHashSet offsetsAfter = collectSoftWrapStartOffsets(1);
assertSame(offsetsBefore.size(), offsetsAfter.size());
offsetsBefore.forEach(new TIntProcedure() {
@Override
public boolean execute(int value) {
assertTrue(offsetsAfter.contains(value + 1));
return true;
}
offsetsBefore.forEach(value -> {
assertTrue(offsetsAfter.contains(value + 1));
return true;
});
}
@@ -298,7 +298,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
"This a long string that is expected to be wrapped in more than one visual line<caret>";
init(20, text);
List<SoftWrap> softWrapsBeforeModification = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
List<SoftWrap> softWrapsBeforeModification = new ArrayList<>(getSoftWrapModel().getRegisteredSoftWraps());
assertTrue(softWrapsBeforeModification.size() > 0);
backspace();
@@ -312,7 +312,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
"Long line2 that is expected to be soft-wrapped<caret>";
init(20, text);
List<SoftWrap> softWrapsBeforeModification = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
List<SoftWrap> softWrapsBeforeModification = new ArrayList<>(getSoftWrapModel().getRegisteredSoftWraps());
assertTrue(softWrapsBeforeModification.size() > 0);
int offset = myEditor.getCaretModel().getOffset();
@@ -475,7 +475,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
init(30, text);
myEditor.getCaretModel().moveToOffset(text.indexOf("}") - 1);
List<? extends SoftWrap> softWraps = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
List<? extends SoftWrap> softWraps = new ArrayList<>(getSoftWrapModel().getRegisteredSoftWraps());
assertTrue(!softWraps.isEmpty());
CaretModel caretModel = myEditor.getCaretModel();
@@ -516,7 +516,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
init(30, text);
myEditor.getCaretModel().moveToOffset(text.indexOf("\n") + 1);
List<? extends SoftWrap> softWraps = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
List<? extends SoftWrap> softWraps = new ArrayList<>(getSoftWrapModel().getRegisteredSoftWraps());
assertTrue(!softWraps.isEmpty());
CaretModel caretModel = myEditor.getCaretModel();
@@ -620,7 +620,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
myEditor.getSelectionModel().setSelection(startOffset, endOffset);
VisualPosition positionBefore = myEditor.offsetToVisualPosition(document.getLineStartOffset(lineToSelect + 1));
List<SoftWrap> softWrapsBefore = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
List<SoftWrap> softWrapsBefore = new ArrayList<>(getSoftWrapModel().getRegisteredSoftWraps());
copy();
paste();
@@ -644,7 +644,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
int end = document.getLineEndOffset(1) + 1;
int visualLinesToRemove = getSoftWrapModel().getSoftWrapsForLine(1).size() + 1;
List<VisualPosition> positionsBefore = new ArrayList<VisualPosition>();
List<VisualPosition> positionsBefore = new ArrayList<>();
for (int i = end; i < text.length(); i++) {
positionsBefore.add(myEditor.offsetToVisualPosition(i));
}
@@ -727,18 +727,15 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
// Simulate addition of the new import that modifies existing fold region.
myEditor.getDocument().insertString(foldEndOffset, "\nimport java.util.Date;\n");
final FoldingModel foldingModel = myEditor.getFoldingModel();
foldingModel.runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
FoldRegion oldFoldRegion = getFoldRegion(foldStartOffset);
assertNotNull(oldFoldRegion);
foldingModel.removeFoldRegion(oldFoldRegion);
int newFoldEndOffset = myEditor.getDocument().getText().indexOf("class") - 2;
FoldRegion newFoldRegion = foldingModel.addFoldRegion(foldStartOffset, newFoldEndOffset, "...");
assertNotNull(newFoldRegion);
newFoldRegion.setExpanded(false);
}
foldingModel.runBatchFoldingOperation(() -> {
FoldRegion oldFoldRegion = getFoldRegion(foldStartOffset);
assertNotNull(oldFoldRegion);
foldingModel.removeFoldRegion(oldFoldRegion);
int newFoldEndOffset = myEditor.getDocument().getText().indexOf("class") - 2;
FoldRegion newFoldRegion = foldingModel.addFoldRegion(foldStartOffset, newFoldEndOffset, "...");
assertNotNull(newFoldRegion);
newFoldRegion.setExpanded(false);
});
CodeFoldingManager.getInstance(getProject()).updateFoldRegions(myEditor);
assertEquals(new VisualPosition(2, 0), myEditor.logicalToVisualPosition(new LogicalPosition(5, 0)));
@@ -1005,7 +1002,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
final String text = "12345678 abcdefgh";
init(15, 7, text);
myEditor.getCaretModel().moveToOffset(text.length());
final Ref<Boolean> fail = new Ref<Boolean>(true);
final Ref<Boolean> fail = new Ref<>(true);
SoftWrapApplianceManager applianceManager = ((SoftWrapModelImpl)myEditor.getSoftWrapModel()).getApplianceManager();
SoftWrapAwareDocumentParsingListener listener = new SoftWrapAwareDocumentParsingListenerAdapter() {
@Override
@@ -168,8 +168,9 @@ public abstract class PerFileMappingsBase<T> implements PersistentStateComponent
if (oldFile == null) continue; // project
oldFile.putUserData(pusher.getFileDataKey(), null);
}
PushedFilePropertiesUpdater updater = PushedFilePropertiesUpdater.getInstance(project);
updater.pushAll(pusher);
if (!project.isDefault()) {
PushedFilePropertiesUpdater.getInstance(project).pushAll(pusher);
}
}
if (shouldReparseFiles()) {
Project[] projects = project == null ? ProjectManager.getInstance().getOpenProjects() : new Project[] { project };
@@ -114,49 +114,14 @@ public class JavaI18nUtil extends I18nUtil {
return false;
}
private static final Key<CachedValue<PsiExpression>> TOP_LEVEL_EXPRESSION = Key.create("TOP_LEVEL_EXPRESSION");
@NotNull
static PsiExpression getTopLevelExpression(@NotNull final PsiExpression expression) {
if (expression instanceof PsiBinaryExpression || expression.getParent() instanceof PsiBinaryExpression) { //can be large, cache
CachedValue<PsiExpression> cachedValue = expression.getUserData(TOP_LEVEL_EXPRESSION);
if (cachedValue == null) {
expression.putUserData(TOP_LEVEL_EXPRESSION, cachedValue = CachedValuesManager.getManager(expression.getProject()).createCachedValue(new CachedValueProvider<PsiExpression>() {
@Nullable
@Override
public Result<PsiExpression> compute() {
PsiExpression topLevel = getTopLevel(expression);
CachedValue<PsiExpression> cachedValue = expression.getUserData(TOP_LEVEL_EXPRESSION);
assert cachedValue != null;
int i = 0;
for (PsiElement element = expression; element != topLevel; element = element.getParent(), i++) {
if (i % 10 == 0) { // optimization: store up link to the top level expression in each 10nth element
element.putUserData(TOP_LEVEL_EXPRESSION, cachedValue);
}
}
return Result.create(topLevel, expression, PsiModificationTracker.MODIFICATION_COUNT);
}
}, false));
}
return cachedValue.getValue();
}
return getTopLevel(expression);
}
@NotNull
private static PsiExpression getTopLevel(@NotNull PsiExpression expression) {
static PsiExpression getTopLevelExpression(@NotNull PsiExpression expression) {
while (expression.getParent() instanceof PsiExpression) {
final PsiExpression parent = (PsiExpression)expression.getParent();
if (parent instanceof PsiConditionalExpression &&
((PsiConditionalExpression)parent).getCondition() == expression) break;
expression = parent;
if (expression instanceof PsiAssignmentExpression) break;
if (expression instanceof PsiBinaryExpression) {
CachedValue<PsiExpression> value = expression.getUserData(TOP_LEVEL_EXPRESSION);
if (value != null) {
return value.getValue(); // optimization: use caching for big hierarchies
}
}
}
return expression;
}
+62
View File
@@ -0,0 +1,62 @@
import sys
import optparse
from django_manage_commands_provider import _xml
class Option:
def __init__(self):
self.long = []
self.short = []
self.arg = None
self.help = None
def dump(self, dumper):
dumper.add_command_option(self.long, self.short, self.help, self.arg)
def parse_option_desc(option_desc):
option = Option()
option.short = option_desc._short_opts
option.long = option_desc._long_opts
option.help = option_desc.help
if option_desc.nargs > 0:
option.arg = (option_desc.nargs, option_desc.type)
return option
def get_options(options_parser):
return map(parse_option_desc, options_parser.option_list)
def dump_actions(dumper, app):
common_options = get_options(app._GetOptionParser())
for name, action in app.actions.iteritems():
dumper.start_command(name, action.short_desc)
args = action.usage.split(name.split(' ')[0])[-1].strip()
dumper.set_arguments(args)
for option in common_options:
option.dump(dumper)
if action.options:
parser = optparse.OptionParser(conflict_handler='resolve')
action.options(app, parser)
for option in get_options(parser):
option.dump(dumper)
dumper.close_command()
if __name__ == "__main__":
sys.path.append(sys.argv[1])
import appcfg
try:
appcfg.run_file('appcfg.py', globals())
finally:
app = AppCfgApp(['appcfg.py', 'help'])
dumper = _xml.XmlDumper()
dump_actions(dumper, app)
print(dumper.xml)
sys.exit(0)
@@ -58,6 +58,8 @@ public enum PythonHelper implements HelperPackage {
DJANGO_MANAGE("pycharm", "django_manage"),
MANAGE_TASKS_PROVIDER("pycharm", "_jb_manage_tasks_provider"),
APPCFG_CONSOLE("pycharm", "appcfg_fetcher"),
BUILDOUT_ENGULFER("pycharm", "buildout_engulfer"),
EPYDOC_FORMATTER("epydoc_formatter.py"),