Snapshot 020d29497847701e84e383d965abf543b80758e2 from idea/133.370 of git://git.jetbrains.org/idea/community.git
020d294: platform: incompatible KTerm option stripped
589c8be: ui: correct icon for facet editor panel
00b8db5: skip invalid highlighters (EA-37197) - 8K reports! (cherry picked from commit 3688a79) [r=Peter.Gromov]
663de5b: IDEA-114952 Eclipse code style import: would be nice to remember imported file location (URL fix for Windows) (cherry picked from commit 7f1b705)
fd13ff8: IDEA-116071 (Field can be final inspection change) (cherry picked from commit e1eab58)[CR-IC-3389]
ae3b411: IDEA-116508 ("Local variable or parameter can be final" inspection use generates uncompilable code not extracting a really finalizable variable) (cherry picked from commit 49639e8)[CR-IC-3388]
e31eafc: EA-52123 (IAE: InvertBooleanHandler.invoke) (cherry picked from commit 18e2e69)
b318047: 2x more compact mapping storage for 7bit ascii paths [r=Eugene.Zhuravlev] (cherry picked from commit 2f10822)
42fa68e: IDEA-117378 Privilege escalation via JetBrains products by local attacker (cherry picked from commit 81b56c6)
87e3a49: IDEA-118063 Gradle: cosmetic fix 'Add gradle plugin' action: 'Choose plugin' popup has lots of not clickable links (cherry picked from commit ca4f7bc)
1245a78: IDEA-117792 Gradle Run/Debug Configuration: support adding Gradle specific parameters; review - http://crucible.labs.intellij.net/cru/CR-IC-3727
8558b99: 13.0.2 with EAP
997edcb: no smart icons and no parameter info in power save mode (cherry picked from commit 4bb3242)
bdd56c0: [^jeka] tolerate mysterious groovy class file corruption
a346506: IDEA-118397 Resume build not working (cherry picked from commit ea2b802) +review CR-IC
a659297: IDEA-118245 Retain the last used command line in the Execute Maven Goal dialog (cherry picked from commit 26a7d57) +review CR-IC
a604811: IDEA-118102 Maven: artifacts name not properly generated from pom in IDEA 13 (cherry picked from commit e610603) +review CR-IC
a8ffcf9: IDEA-118053 Editor "deprived of mind" when editing settings.xml (cherry picked from commit ed529d5) +review CR-IC
0e9a065: IDEA-78508 [Maven] Good Code Red with empty variables in classifiers (cherry picked from commit 0831af1) +review CR-IC
cbd34cb: IDEA-116921 Run configuration can't resolve test dependency when "Resolve workspace artifacts" ticked on. (cherry picked from commit d06f31a) +review CR-IC
75e374a: Fix for IDEA-116940 @formatter off still generating braces [CR-IC-3478] (cherry picked from commit 3340beb)
1f6f81f: avoid unconditional trace properly (cherry picked from commit 2e72fcc)
5f45643: Compilation fix
a4749db: IDEA-118292 (process idea.properties in declaration order)
679e1c4: IDEA-118111 (OpenJDK 6 check made strict)
950225b: restore classes in nav bar (IDEA-118168)
cfe1124: NPE
0a41d99: method may be static: process default methods (IDEA-118272)
6ff67d9: redundant cast: ensure that temp variable would have unique name (IDEA-118197)
9549258: distinct prover: distinguish types when type parameter has bounds (IDEA-118037)
0dcb258: show param info: highlight overload vararg method
c40975b: method references: smart completion to filter by return type
319017d: disable lambda completion after inserted qualifier
ed361ec: do not register fixes which need editor in batch mode (IDEA-116248)
30cba59: EA-52652 - NPE: ExceptionUtil.getUnhandledExceptions
c9199b7: redundant type args: process nested calls (IDEA-117945)
fad3ead: IDEA-117989 JUnit: Run/Debug java test output "scroll to stacktrace" not working as expected
c9d58cc: IDEA-117911 Delegate methods duplicate @Override
35afc12: generate javadoc: search for modules under progress
bf0ec72: IDEA-117883 make <--tooltip end--> logic work in Inspections View; provide additional tooltip bounds
056b529: new inference: propagate outer method to constraints, initial (IDEA-117803)
cd65706: IDEA-117827 Invalid "ambiguous method call" error
8251b5d: IDEA-117780 Bad code is green: non-static class T cannot be referenced from a static context
4a1ae2f: restore suppressions (IDEA-117763)
b7003c6: pull up: ignore conflicts coming from access object when it is also moved (IDEA-117671)
282c332: remember different working dirs for rerun (IDEA-116110)
8224a17: scope to check for cheap search (IDEA-117665)
b2affde: refactoring high level listeners (IDEA-115905)
a2ae64e: NPE
f75829b: extend local scope a set of containing files as visitors expect file level (IDEA-117649)
c72c42f: tests notification: separate not started notification from ignored when no 'not started' tests were detected (IDEA-116825)
5a0aebc: suspicious names: highlight only variable name (IDEA-116475)
62ba24a: disable introduce variable from part of literal expression which is not a string
740bbf2: testng: ignore default annotations attributes (IDEA-117575)
52c384c: add explicit arguments: eliminate wildcards (IDEA-106741)
31e57cc: check lambda return values during constant&conditions (IDEA-117420)
c8ff7ea: javafx: allow to configure custom manifest attributes (IDEA-115252)
99b89cc: IDEA-117314 Can not compile Java project with Eclipse dependencies storage format
528f2d5: introduce variable inside lambda: do not step out of lambda block
48cb2be: IDEA-117252 Extract variable bug
8724806: IDEA-113339 "replace with method reference" ignores side effect of expression: ignore any new expressions in qualifiers
6f6d61b: lambda -> method ref: do not convert if resulted ref would be ambiguous (IDEA-116964)
d9a89a1: EA-52426 - NPE: JavaDocInfoGenerator.generateSuperMethodsSection
df01945: IDEA-118264 Rearrange Entries stopped working in Intellij 13
5e7d560: files compiled on first round may require additional recompilation on the next round (second part for IDEA-116914) constant search on the IDE side rewritten: only direct dependencies are returned for each search round; all transitive dependencies will be additionally handled by make
4792865: handling cases when added class hides imported class with the same short name (IDEA-116914 Incremental compilation of Java project fails)
e99d464: correct check
ea90776: safely skipping some invalid usages
3a16b61: proper synchronization
0c9c72e: IDEA-117249 Optimize make's constant search algorithm, so that read action is not held for long time
f19231c: do not search usages of removed constant fields in injected PSI
d6ef061: Merge branch '133' of git.labs.intellij.net:idea/community into 133
fa65f8e: IDEA-35996 Ant integration: provide more informative message in case ant file execution is stopped due to unknown command line argument
9519530: IDEA-117904 Ant integration: running: with an error (javac) the result is reported as "successful": perform all status calculations after all messages are processed
5a9f9a8: IDEA-111702 Java Rearranger illegal forward reference on fields rearrangement [CR-IC-3034] (cherry picked from commit 7f01bcd)
a2dd3a6: IDEA-115786 Allow the number of Maven threads to be specified (cherry picked from commit 9d05ff2) +review CR-IC
abfd9a5: IDEA-114418 (Grails SDK of an dependency) -Dgrails.disable.structure.update=true should work for JDK synchronization. (cherry picked from commit 009ca28) +review CR-IU
491ceb6: IDEA-96723 Java Rearranger deletes blank lines in field declarations (cherry picked from commit 15869e7)
85fe89f: IDEA-118159 "Search Everywhere" inconsistent api on ItemPresentation (cherry picked from commit 9729ea9) [r=Konstantin.Bulenkov]
bcf528b: revert platform fix for PY-6095, apply Python specifix fix instead (cherry picked from commit 0dfae8b)
fec8fe7: IDEA-117864
930439c: cosmetics
6c1df41: IDEA-108838 Wrong code when introducing variable in injection (cherry picked from commit f119c2e)
2a40aeb: Merge remote-tracking branch 'origin/133' into 133
d92cdcc: IDEA-117391 (annotation highlighting fixed)
05a20ae: IDEA-117772 (start application loading in EDT)
ef18d70: DevKit: refine DOM stubs + test (cherry picked from commit 84d8e52)
15d7962: IDEA-117583 DevKit: highlight <idea-version> "min"|"max" as deprecated (cherry picked from commit ce277a1)
be71e9a: cleanup, update "since-build" (cherry picked from commit f56ca26)
e9aa79b: IDEA-117573 DevKit: highlight <vendor> "logo" as obsolete (cherry picked from commit d552ee4)
d5d86be: EA-52563 - assert: ChooseModulesDialog$MyTableCellRenderer$.customizeCellRenderer (cherry picked from commit d24d279)
009d144: CodeInsightTestUtil#doIntentionTest(): remove Throwable declaration (cherry picked from commit d7e8e2a)
e543b44: lazy class loading for PtyProcess (r=Eugene.Zhuravlev), 2 (cherry picked from commit 85700e4)
edd9c56: save / load per project key hash codes (cherry picked from commit c847d67) [r=Eugene.Zhuravlev]
eff72da: avoid garbage creation in JDK7 due to calling StringBuilder.toString() that copies buffer now (cherry picked from commit 03f7413) [r=Peter.Gromov]
40c73d4: no need to create strings of PsiFile's Text when we can avoid it or use charsequence (cherry picked from commit d8ec59b) [r=Peter.Gromov]
10c479c: introduced cvs.roots.refresh.uses.vfs property (true by default) and uses its value to refresh cvs roots after update using vfs to avoid performance problems (IDEA-112132) (cherry picked from commit 1958e9a) [r=Peter.Gromov]
8cac2e5: - detect proper encoding for html5's <meta charset="charsetname"> - [performance fix] avoid (light) parsing of html content if there is no charset\s*= pattern inside the string (cherry picked from commit 2f4be38) [r=Alexey.Kudryavtsev]
cee6644: IDEA-78206 Constructing 'mailto' link -> cannot resolve file 'mailto' (cherry picked from commit 3166c04) [r=Konstantin.Ulitin]
98571ff: Cyclic Expand Word leaves word highlighted (IDEA-115727) (cherry picked from commit 29bb231) [r=Peter.Gromov]
31fe1a1: refixing IDEA-57940 : the variants from other editors are suggested AFTER finishing variants from current file (cherry picked from commit e76fe51) [r=Peter.Gromov]
e3975be: avoid allocating sun.nio.cs.US_ASCII$Decoder when converting byte[] to String
1053bdb: don't create TIntArrayList(DEPTH_LIMIT) before we have clear indication that we might have a loop (parentId >= id) (cherry picked from commit 5478fdf) [r=Alexey.Kudryavtsev]
364e80e: avoid unconditional trace (cherry picked from commit 2e72fcc) [r=Alexey.Kudryavtsev]
70980d8: don't call toString() without need to avoid garbage (cherry picked from commit 75c030c) [r=Alexey.Kudryavtsev]
466dc64: Apply again "update stubs per filetype reverted for 133 branch"
3f66295: Apply again "IDEA-113684 Soft wraps insert additional spaces"
028b3ae: Darcula: combobox as cell renderer/editor fixes
e96975a: fix default size of SourceMapInspector window (cherry picked from commit a64047e)
edfb4da: if IDEA sees text/plain and extension .java, perhaps it should infer that it's actually Java, because not everyone will set up their HTTP servers with language-specific mime types? (Particularly when following a URL to a source file in a sourcemap.) +review (cherry picked from commit 5ea95e3)
6162222: fix ClassCastException: com.intellij.openapi.fileEditor.FileEditorState$1 cannot be cast to com.intellij.openapi.fileEditor.impl.text.TextEditorState (cherry picked from commit 44f0697)
6c8dbc0: update progress on test done (finished, failed, or ignored), not on test started (cherry picked from commit dbcb907)
a4038dd: REGISTERED state added (cherry picked from commit 08677f9)
bf0da3a: fix PersistenceRenameTest blinking: inconsistent @NameValue placement and random methods order in DomGenericInfo
1f08879: PsiBuilder/GPUB: zero-length token parsing support (lexer-based macros)
352056d: EA-52484 - IOOBE: ConsoleHistoryModel.getHistoryPrev
21ab06f: EA-52027 - assert: TextRange.<init>
b452663: IDEA-116383 cannot reconnect Some RuntimeException contains not serializable class 'org.apache.maven.model.building.DefaultModelProblem'. So IDEA throw java.rmi.UnmarshalException caused by java.io.NotSerializableException. (cherry picked from commit 9f7fb6c) +review CR-IC
a4e9447: Revert "IDEA-113684 Soft wraps insert additional spaces"
231adec: Revert "update stubs per filetype reverted for 133 branch"
d62a526: use method instead of manual hack
cae16e2: better combobox rendering on aqua: no focus ring around combo button, fixed 1px size difference
7d9b58c: fix TextFieldWithHistory rendering on mac
95d40df: determine tag end by doctype #WEB-2229 fixed
556c3bc: lazy class loading for PtyProcess (r=Eugene.Zhuravlev) (cherry picked from commit 96c8bca)
749d89f: RUBY-14672: better name for gracefulProcessTermination() (reviewed by Dennis Ushakov and Sergey Simonchik ) (cherry picked from commit 908538b)
dd5dd11: RUBY-14672: we need to send SIGINT to Ruby debugger twice (reviewed by Dennis Ushakov and Sergey Simonchik ) (cherry picked from commit 4546732)
3c01a72: Merge remote-tracking branch 'origin/133' into 133
6378e77: [git] IDEA-118265 Fix showing Git Branches menu
b9446e2: close process's input stream after process termination (cherry picked from commit e962648) CR-WS-272
c8fbe68: support Windows soft kills using runnerw.exe in KillableColoredProcessHandler (cherry picked from commit 77e0f1a) CR-IC-3459
988c990: fix showValuePopup — incorrect scrolling (cherry picked from commit 594785c)
1f67166: IDEA-105450 Attribute id in OSGI reference element not allowed: XmlHighlightingTest.testXhtmlSchemaHighlighting fixed (cherry picked from commit 69daed6)
eb3a323: IDEA-105450 Attribute id in OSGI reference element not allowed: get schemaLocation from import tag (cherry picked from commit ec44bbd)
8bb9587: IDEA-105450 Attribute id in OSGI reference element not allowed: namespaces from standard resources should be considered relevant (cherry picked from commit d30684d)
a129c6c: IDEA-84166 Support "CTRL+H" on class in .xml file (cherry picked from commit da3cbf3)
7162d4b: update stubs per filetype reverted for 133 branch
377bf70: IDEA-113684 Soft wraps insert additional spaces (cherry picked from commit 0e1c820)
643cd5d: use direct call to storage.resize() so that IOException is not masked with RuntimeException (IDEA-118107)
2e7c85f: Plugin for IDEA 133.286 3.0.1 EAP CE
f75f35e: Merge branch '133' of git.labs.intellij.net:idea/community into 133
9186d35: PyCharm 3.1
58936a1: add create method
ecf556d: do nothing if state didn't change
dcfbfb5: IDEA-115859 Presentation mode is broken
1d6443d: Javascript tests fixed, IDEA-113977 Formatter: caret is moved on next line if closing brace has wrong indent [CR-IC-3034] (cherry picked from commit dd55e70)
b75041b: Merge branch '133' of git.labs.intellij.net:idea/community into 133
2a74e83: Pty lib updated - run in console mode.
390900e: Guava and Pty4J libraries dependencies.
10a39d8: Contains in branches feature implemented for mercurial log.
37a14b0: Added logging.
9355a2b: improved user experience with run configuration producers
78e57f9: Better multiline code handling in console.
fc7702f: Correct test data path.
6bba62d: Detect SQL fragments only in the beginning of string literals
ba5ff19: Fixed LiteralTextEscaper.getOffsetInHost() for partial ranges inside host that contain escapes
df0c579: Added caching of decoded fragments of string literals
f93a871: Fixed detecting file references in Python strings without delimiters
01bf006: Removed unused PyStringLiteralExpression.iterateCharacterRanges()
147ed7a: Switched to new string value iteration in Python file references inside string literals
f8e775c: Use Pair instead of a custom class
0106a10: Switched to new string value iteration in Python spellchecker
69ac8c5: Added PyStringLiteralExpression.getDecodedFragments()
d703ca5: reverted module type from plugin_module to java_module for localization and rest
2cb9a61: fixed tests since we don't propose to make static decorated method
d6ed1d7: fixed PY-10998 Wrong highlight in rst (restructured texts) for headlines
5511e2f: Fix NPE.
9f0c134: Don't break compatibility (PY-11499).
f80fc2e: fixed PY-11500 False positive in method may be static inspection for decorated methods
0bfaaf2: fixed PY-2984 Surround with try/except reformats entire file
0ed12da: args can be immutable (PY-11465).
1bb8318: fixed PY-11435 Can't run script by context menu action if it has method named test
0336898: Fixed detection of the largest string literal for right parts of '%' operator
cb5714e: fixed PY-11452 tcunittest errors with single-character failure message
2503a60: fixed test data
16aa28c: fixed PY-11476 No error given for mismatched accolade and squarebracket
403b937: Allow to run processes with PTY.
4740054: Added comment-based language injector for Python
f56fecc: fixed tests
45a824c: Fixed un-inject language availability for temporary Python injections
ea707eb: Method renamed.
4b349d3: Extracted PyInjectionBase.registerInjection
909a31d: Don't inject any language into percent-based Python formatting even without formatting operator (PY-10771)
b928248: Fixed SQL select IntelliLang pattern (PY-10926)
55239bf: If command executed but is incomplete and more lines are needed prompt shouldn't be changed to ordinary one in this case.
a061c7e: Fix modified console options modified after creation.
52b6eb3: Jython doesn't support 'exec' symbol in interactive console.
1213be2: PyConsole: correctly indent after execution of incomplete multi-line string.
38b4e20: Fixed execution of incomplete multiline code fragments.
5306cfb: First evaluate more then add to queue.
4f18cfe: Simplified.
9688ef7: Attribute renamed.
10a0e30: NotNull annotation.
5e5c546: Fixed IPython and debug console broken by console execution model changes.
e53607e: Fixed write lock assertion.
78ea78d: Execute multi-line code fragments by runsrouce with 'exec' option instead of one line by one (PY-10769).
0dcf990: Cleanup.
9f4dca96: Broken indentetion in console fixed (PY-10776).
3c4550e: Fixed saving of env in console settings. Mappings format saving changed.
699255f: Fixed working directory setting in console settings.
9b98ce9: Fixed saving path mappings in console settings (PY-9855).
14fbafd: Don't ask to reconnect remote interpreter in case of fail as it never helps but causes problems (PY-10590).
f8a096a: Support for temporary and configuration-based IntelliLang injections in Python (PY-10983, PY-10721)
5def9d3: fixed http://youtrack.jetbrains.com/issue/PY-2953
e6a24df: fixed PY-11394 "no tests were found" with django 1.6 DiscoverRunner
1fb4a8a: used consistent name prefix
923f8c0: fixed PY-11415 GAE: Lazy Handler reference is not updated when moving to other module
0a3c840: fixed PY-9967 App Engine: do not resolve to installed to interpreter library
ea42fbf: [log] Fix showing dot in the root table header
decac91: [log] Fix background of the details panel content (cherry picked from commit 2ad2cba)
224a2be: [log] fix name of variable
f79c2e4: [log] IDEA-115675 IDEA-116040 Fix table columns sizing
668c021: [log] IDEA-117500 Don't repaint branches panel on every updateUI
ed4a8ca: [log] IDEA-117500 Optimize grouping of branch references
a98e6c8: [git] Don't modify the unmodifiable collection (cherry picked from commit 007dc0d)
9321b17: [git] IDEA-117500 Don't copy, just wrap in unmodifiable
f3cd826: [git] remove unused method
d7db0fc: [log] Separate loading indicator for "Contained in branches"
ab8606f: [log] Fix "Containing branches" for filtered list & for Mercurial
c190668: [git] Move & rename method to get branches to GitBranchUtil for reuse (cherry picked from commit f78700e)
0ae4458: [git] Simplify method to get branches: use branch names.
423dbc6: IDEA-117936 IDEA13 fails to stop at breakpoint inside advised method
4587a46: IDEA-117613 Gradle: tool window is missing after the update, safe check for newly created project added
18e44f3: IDEA-117613 Gradle: tool window is missing after the update review: http://crucible.labs.intellij.net/cru/CR-IC-3629
b9b4c6c: fixed IDEA-111701 Emacs: pressing Ctrl+k several times should add lines to muti-line buffer (regression for IDEA-18764, broken in IDEA-111275)
a843386: we must not use getKnownFileTypeOrAssociate on navigate (cherry picked from commit 476b30d)
cf363b6: fix actionSystem.fixLostTyping.description (cherry picked from commit caf3ece) CR-IC-3481
4dfe767: IDEA-117548 Bad function parameters highlight (cherry picked from commit d4507c9)
b83ac23: fix assertion (cherry picked from commit 5743c3c)
f7e5eeb: WEB-10231 first navigation to http file doesn't open desired location (cherry picked from commit 384f8f9)
fe39b87: wait smart mode checks for isReadAccessAllowed too, so, we must not call it (cherry picked from commit a5dd92c)
f4c9d17: optimization — check isEmpty (cherry picked from commit 44727c2)
cd8fb58: VmFileEditor — prepare to fix postponed navigation problem in our HTTP file editor. VmFileEditor supports postponed navigation. (cherry picked from commit db4ca37)
c669320: "Run in background" option from now on means "show build messages immediately" rather than "execute with modal dialog"
d83aedd: don't generate large substrings when creating CompletionResultSet [r=Peter.Gromov]
87ad24b: 13.0.1
14361cd: avoid easy garbage java.util.ArrayList$Itr: 1,720,417,512 (1%) bytes in 71,684,063 (2%) objects (avg size 24 bytes) java.util.ArrayList.iterator: 1,720,392,864 (99%) bytes in 71,683,036 (99%) objects com.intellij.openapi.projectRoots.impl.ProjectJdkTableImpl.findJdk: 938,831,640 (54%) bytes in 39,117,985 (54%) objects com.intellij.openapi.editor.impl.ComplementaryFontsRegistry.getFontAbleToDisplay: 218,420,520 (12%) bytes in 9,100,855 (12%) objects (cherry picked from commit 9207b87) [r=Peter.Gromov]
41efe97: look for xml properties in files with xml file type only (cherry picked from commit b6ae811) [r=Dmitry.Avdeev]
ea2590e: WEB-10191 Weird field in the Configure NodeJS Modules Sources (cherry picked from commit 0f61ced) http://crucible.labs.intellij.net/cru/CR-IC-3556
a2b39c2: Gradle: fix dependencies scope merge IDEA-117556 Gradle custom provided configuration added with compile scope IDEA-117601 Gradle integration ignores scopes.TEST.plus in build.gradle (cherry picked from commit f80d692) Safe hotfix, the code works in a separate process (in gradle daemon, not in IDE process)
ce53010: External system: build files modification triggers threads continuously if "auto-import" feature enabled review- http://crucible.labs.intellij.net/cru/CR-IC-3533
4d9ae0c: Gradle: fix dependency scope merge to respect artifact classifier option related bug - IDEA-117627 Transitive dependencies missing from imported Gradle project Safe hotfix, the code works in a separate process (in gradle daemon, mot in IDE process)
d9c3f83: IDEA-117669 gradle multi-module project executing subtask uses wrong gradle version review - http://crucible.labs.intellij.net/cru/CR-IC-3564
87819e2: Gradle: IDEA-116880 Intellij 13 doesn't auto-save files before Gradle task (cherry picked from commit e5c53c6)
5b87b39: Gradle: fix MultipleRepositoryUrlsInspection to operate on gradle-relevant files only (cherry picked from commit 95fbdc9)
1c2f07c: IDEA-117432 Do not fail while resolving client factory for upgrade if "other factory" is configured incorrectly (cherry picked from commit 0694e5d)
d11b435: IDEA-117432 Do not fail while resolving client factory for checkout if "other factory" is configured incorrectly (cherry picked from commit 6242d70)
db15422: Branch information checks moved to appropriated separated methods. (cherry picked from commit 9492982)
6f85df3: Method name simplified (cherry picked from commit 0924c2b)
16e2328: IDEA-115906 Throwable ; IDEA-117401 IAE fixed
eedd7fe: HEAD branch filter in new log fixed (cherry picked from commit 7793e6f)
a787eb2: VcsRootDetector and NotifierError tests fixed (there were .git in T ot tmp dir above, so appropriate checker found its root,then error)
ddc643d: remove outdated and buggy (in case of library code) property java.debugger.xBreakpoint.onlyIfHasFacets (cherry picked from commit 5b7f60f)
ab9cce8: CR-IC-3511 CFR-63806 (cherry picked from commit e800ade)
d3e739f: introduce newUrl (cherry picked from commit bb94f47)
5009fbf: VisualizeScriptSourcemap action (cherry picked from commit 2694a1f)
2051c1e: cleanup (cherry picked from commit 30d4cdf)
586ef62: Merge remote-tracking branch 'origin/133' into 133
3a93fee: rollback IDEA-117378. It will be available in 13.0.2
d72ed2a: IDEA-117227 load imports from stubs [^Peter]
5568b0d: Groovy: injection in command expression [^Peter]
b0ef47e: IDEA-117389 Groovy: Introduce constant from string part [^Peter]
7076f89: IDEA-117227 stubs for Groovy imports [^Peter]
605a0a9: IDEA-117390 'IntelliJIdeaRulezzz' in Code Completion [^peter]
ac4417e: fix testdata
8607b4d: IDEA-116547 optimization in reassigned vars check [^peter]
1e7c610: WEB-10019 Don't show emmet preview after simply dot (cherry picked from commit 127560f)
4b36aad: WEB-9986 CSS: fuzzy search shows turned off abbreviations (cherry picked from commit 56e0385)
4b4958e: WEB-10017 New "Surround with emmet" popup breaks usability (cherry picked from commit 8bdc013)
0bd5b71: automatically starts rebuild if java builder caches are corrupted (IDEA-117024) [rev by Jeka]
f536c49: Merge remote-tracking branch 'origin/133' into 133
81b56c6: IDEA-117378 Privilege escalation via JetBrains products by local attacker
633cd5e: a temporary workaround for HiDPI on Windows/Linux
b7a8a38: Local VCS tests quick fix (ignore temp. FS)
eecd3d1: make history almost unlimited
72de836: no delay after tab or escape
96b5a46: re-create components on every call (laf change fix)
9aa347b: Extracted Python path walking and fixed broken symlink check (PY-10534)
66b3393: differentiate between Sun and Oracle VMs
6b27a51: fixed silent installation mode.
0e4a0fc: IDEA-117378 Privilege escalation via JetBrains products by local attacker IDEA-113862 Confusing Run as dialog
a7300cd: [^maxim] FrequentEventDetector: log outside of synchronized (IDEA-117426)
9d0b588: [^nik] GroovyHotSwapper: use FileTypeIndex
3228a63: [^nik] cache GroovyHotSwapper.containsGroovyClasses (IDEA-116851)
57ff2da: IDEA-103199 Undo: UTF problem (after-review improvements) (cherry picked from commit 0a0aecf)
75ed596: IDEA-103199 Undo: UTF problem (cherry picked from commit ea49ecf)
0a705a8: correct definition of "oracle vm" for java 6
7464e2f: can not clear JarFileHandler caches (e.g. on JDK 7) -> no logging (cherry picked from commit 5012a9b) [r=Alexey.Kudryavtsev]
299f014: IDEA-117498 Caret locks up after using ctrl+tab to switch editors [r=Peter.Gromov] (cherry picked from commit 38f2f05)
99b71dc: IDEA-117494 133.193: Importing grails modules not labeled as grails enabled +review CR-IU (cherry picked from commit 588cd01) reviewer: Peter Gromov
48ce506: do not auto-switch current suspend context if a new thread with suspenPolicy=thread hits a breakpoint (IDEA-116160)
64dc9f5: CR-IC-3489 restore old API
f1dcd4c: Merge remote-tracking branch 'origin/133' into 133
4b41e83: [log] IDEA-117365 Expect "empty" git tag; protect against errors
725c360: [log] Register disposable right away, not after initialization (cherry picked from commit 1e48680)
265d0df: EA-51913 - assert: DomNamespaceKeyIndex.hasStubElementsWithNamespaceKey (cherry picked from commit 6763822) CR-IC-3472
42ecb1a: CR-IC-3471 (cherry picked from commit b213f10)
89ee113: finalize consts (cherry picked from commit 73b245e)
d033d07: gwt, ability to debug — one idea module to many gwt modules (cherry picked from commit 8086f92)
056f905: NullFileEditorState +review (cherry picked from commit 561c8d1)
ca7af60: overrides (cherry picked from commit aaa236a)
4f2af9c: CR-IU-366 (cherry picked from commit 40ae21d)
c8c0d46: Problem — we use short gwt module name (Hello) instead of output name (hello, rename-to specified in Hello.gwt.xml). 1) if rename-to specified, url will be http://localhost:9876/sourcemaps/{rename-to} rename-to=“hello” => http://localhost:9876/sourcemaps/hello 2) if rename-to is not specified, url will be http://localhost:9876/sourcemaps/{qualified name} com.google.gwt.sample.hello.Hello => http://localhost:9876/sourcemaps/com.google.gwt.sample.hello.Hello
40f41b5: IDEA-116260 ISE: RPC handler object "AddOnlineUser" not found at com.intellij.ide.XmlRpcServerImpl.process (cherry picked from commit 5aa9b8e)
3265387: enable all lafs by passing a special registry key
bf2b0c6: Rename "Java" -> "JVMOptions" so MacOS doesn't require java 1.6 download from Apple.
c825894: [log] Make fields volatile
3cc0a09: [git] IDEA-116690 Fix "Select in Git Log" from File History
8b85de3: fixing IDEA-117328 java.lang.NoSuchMethodError: com.sun.tools.javac.util.Paths.clearPathExistanceCache()
7e1850e: Merge remote-tracking branch 'origin/133' into 133
f2aed4c: IDEA-117347 Search Everywhere popup is too wide
3675b82: merging ConcurrentMapFactory and ContainerUtil
98ef79b: fix Url equality (scheme) (cherry picked from commit e668634)
290e4a4: fix NPE — url could be in any form, so, parsed can be null (cherry picked from commit ec22c2e)
f90eaba: allow V8 map on IBM JDK 1.7
845ffae: do not disable "ext.dirs" location, because IBM jdk stores some of its essential jars there
5278615: EA-52516 - IAE: HighlightUsagesHandlerBase.addOccurrence
cae4139: EA-52505 - NPE: MethodCandidateInfo.getPertinentApplicabilityLevel
9b6b81e: default concurrency level upper limit
91cefef: encapsulation of factory's implementation details
1081168: IDEA-117298 Darcula&IntelliJ on Windows: Inspection description is too small in Settings
7799dc3: IDEA-117095 Goto File: checkbox 'include non-project files' is remembered between invocations [r=Anna.Kozlova] (cherry picked from commit 7cf6caa)
8eecc0f: all code in "util" module to create CHM implementation via dedicated factory (see IDEA-116404 Java code compilation does not work with IBM JDK)
81ae633: [Filechooser sheets] IDEA-102449 Mac OS + JDK 1.7: dialog sheets go to background if focus is moved from IDEA and then back
ea058b0: fix NPEs
8fbca43: Remove broken dependency on 'markdownj' from tasks-core module
5c1098b: IDEA-117258 IntelliJ theme: selected tabs in Debugger and in Run <application server> views get black color
5e02eb3: IDEA-116558 Update state transition requests for JIRA REST API 2
c2f531a: "read access" assertion and NPE fixes
ea4f96b: fix "read access" assertion
787438f: IDEA-117265 java.lang.ClassCastException: com.intellij.psi.impl.source.tree.java.PsiParenthesizedExpressionImpl cannot be cast to com.intellij.psi.PsiCallExpression
99ae1f5: NPE on invalid expressions
ffc7fa5: IDEA-115953 Editor: Line Spacing < 1.0 no longer works (reviewed by Roman Shevchenko)
886b675: External system: add support for different naming of external entities within IDEA models. E.g. external lib name: 'somelib' -> IDEA lib name: 'Gradle: somelib'. external module name: 'some/module' -> IDEA module name: 'some_module'. (cherry picked from commit bb941b0)
0634d95: enable abbreviations (cherry picked from commit 0ecc836)
1dc77a9: more searchable options
31750db: fix history and symbols 'More' action
bc4db67: Merge remote-tracking branch 'origin/133' into 133
84f584a4: add new actions
5a49390: change action place to Main Menu
4a50f96: don't use smart search for files (don't use space as a separator)
93dd505: ready to nulls (EA-52470 - IAE: TypeCompatibilityConstraint.<init>)
174531a: EA-52436 - IAE: PsiElementFactoryImpl.createType
e58f16d: IDEA-115412 Diff window is minimized after the appearance (cherry picked from commit b2307d0)
8146462: IDEA-117059 (error reporting in updater fixed)
be1c105: NPE in mouse handler
a460658: IDEA-111388 Built-in server not "available external" — it is unclear that port number must be also changed (cherry picked from commit 6ccdae5)
dfdaaae: continue WEB-9968 Dart: ClassCastException when debugging web application in Dartium (cherry picked from commit c19e163)
ee28c75: newHttpUrl — authority must be NotNull (cherry picked from commit a708a6e)
01efd39: NetUtils.tryToFindAvailableSocketPort (cherry picked from commit fa39c70)
ca466c8: introduce Urls.newUri, prepare to fix WEB-9968 Dart: ClassCastException when debugging web application in Dartium (cherry picked from commit 4ecac7f)
e6b739a: IDEA-117059 (same temp. directory for updater)
2679834: introduced idea.register.bundled.fonts registry to be able to switch off bundled fonts registration in order to avoid garbled text in editor (IDEA-93404) [r=Konstantin.Bulenkov] (cherry picked from commit e2cdb6d)
16eb783: fix null project
05de913: report missing optimizedFileManager only once
1b747fe: correct place for optimizedFileManager.jar
4713bfc: Merge branch '133' of git.labs.intellij.net:idea/community into 133
c2c0281: Jediterm updated.
26cf0f4: Mouse selection should always work in Terminal (IDEA-117210).
1f68d01: reconfigure navbar toolbar actions
1ae092c: show separators in navbar toolbar
afcfe95: Setup composite as it is done in EditorImpl.paintComponent.
66f161d: Behave the same as EditorImpl.
013c138: Use Source Code Pro as we don't have problems with unprintable pseudo-graphics as we iterate fonts to find suitable one for unprintable characters.
9796737: special icon for generated test root [rev by Peter]
2398eb9: make adapt_builder_() overridable (initState -> public)
2ef1c62: [git] Quick-fix for IDEA-115581: don't fail, just skip such hashes
1578562: [vcs] IDEA-109608 Apply patch: Fix path detection for new files + test
080813c: update Source Code Pro to version 17
f9c2953: IDEA-117211 empty elements in Search Everywhere
32ebdf3: error reporting in 'Project Structure' dialog: merge UI updates (IDEA-116808, IDEA-110799) [rev by Maxim M.]
2bab20f: added quick-fix to delete all unused libraries (IDEA-99885) [rev by Maxim M.]
f069657: disable GroovyShell because it doesn't work on win {^Peter]
637a5ba: Merge branch '133' of git.labs.intellij.net:idea/community into 133
dd8e18a: moved to core-impl
47f94f0: IDEA-104734 Dracula: Cannot see well active tab in Modules Settings
e2c1637: removed LOG.error for null syntax highlighter (cherry picked from commit 3e4c22c) [r=Peter.Gromov]
d4240b2: check that index for which indexUnsavedDocument is performed can be applied to given file type (EA-47740) [r=Eugene.Zhuravlev] (cherry picked from commit 0057f81)
acede1f: Merge branch '133' of git.labs.intellij.net:idea/community into 133
5ffb206: PsiSearchHelper changes cherry-picked (r:Peter)
1669188: avoid blocking runReadAction in debug logging
ba70dd4: Minor typo fix (IDEA-116432 Incorrect Spelling of Eclipse) (cherry picked from commit 3c553d6)
aadedc9: IDEA-117192 NavBar popup shows in wrong place when navigating to the directory from popup
c3b6615: Merge remote-tracking branch 'origin/133' into 133
a915da31: Merge remote-tracking branch 'origin/133' into 133
9a90c16: IDEA-116866 (path overriding for plugins/log dirs fixed once again)
bc3d847: Merge remote-tracking branch 'origin/133' into 133
6081b4f: removed signing for CE launchers.
21cd0c7: tuned UI for got it button
f986c7c: method refs: do not choose more specific method between methods with different number of params
aa7db43: IDEA-116756 Gradle multi-module project with deep-nested modules - idea places iml file in the wrong directory (cherry picked from commit 8e2ad06)
3bd2a55: plugin advertiser: ensure that older plugins won't be ever suggested
f739564: plugins advertise: download plugin if it was not explicitly disabled (IDEA-117003)
df398a9: plugins advertiser: provide loading plugin version for renderer
751d401: CCE (IDEA-117119)
03b253b: lambda: do not distinguish between ellipsis and arrays for formal lambda params checks (IDEA-117124)
ca191c9: index property optimization [^Peter]
4f7ba3a: class searching optimization [^Peter]
4e7ff49: IDEA-116628 No nulls in type parameters [^Peter]
a30f59b: typo [^Peter]
580cb5e: Merge branch '133' of git.labs.intellij.net:idea/community into 133
9c2489a: Take default shell from env variable.
9b2b7f3: File chooser for shell path (PY-11334).
9758753: Take shell path setting before every process creation.
3dbe4eb: use the same background color
8b8c0df: set lower limit of 1 for max_worker_threads_count (for low-profile cpu)
2a67fed: test for unzipping malformed zip archive (cherry picked from commit cd35a94) CR-WS-267
2c74d46: target error message for a newly created project (cherry picked from commit 8e10c3a) CR-WS-267
41311ea: use ZipFile, because it throws exception for a malformed zip archive (cherry picked from commit 02da50f) CR-WS-267
323523c: make IntelliJ laf by default on Linux
9d74b04: update artwork for version 13
d7ce47d: add history
42733a8: utility class holding two colors for gradient painting
537dd04: better colors? fix balloon and popup borders
787ec72: added signing for community launchers in zip distr.
f577493: use backported V8 CHM only for Oracle or Apple JDK (IDEA-116404 Java code compilation does not work with IBM JDK)
ae19efc: isEap = false, no error reporting
7e1f100: ~update mockJDK-1.7 used classes to be at least from jdk 1.5
c812622: do not create raw outer types during diamond inference
d0bc4ad: Merge branch '133' of git.labs.intellij.net:idea/community into 133
b6fe06f: FinderRecursivePanel: do not perform getListItems() in EDT on update (cherry picked from commit a128fa5) CR-IC-3413
e189085: IDEA-116866 (path overriding for plugins/log dirs fixed)
c50b1f1: Cleanup (punctuation)
cf75962: External System: support for multiple tasks execution added (cherry picked from commit a6f9141)
60418e9: IDEA-100294 Cannot edit a file - text jumps all over the screen (cherry picked from commit 36bacc0) [cdr]
3da28ad: Merge remote-tracking branch 'origin/133' into 133
86b3924: mock 1.8 jdk
ae8c2b0: switching to java.util.ConcurrentHashMap in jps code; eliminate unneeded map queries
f3d2761: EA-52322 (diagnostic)
f0d71c1: copyright: fix for 2 open projects
e797eb4: javadoc: keep whitespaces in {@code} tags (IDEA-109997) (cherry picked from commit d08af6dfed35217f3bb03093e8c549ec3065d258)
aa52879: IDEA-117082 Anonymous class assigned to final field (cherry picked from commit 02cabc4e849835259d9d837f86493c5e4ff7269c)
c040d2f: junit: do not reuse directory configuration from another test root (IDEA-116871) (cherry picked from commit 354fece7efab569fa05b135ab912bee758a6d3f7)
99043c6: junit: do not create directory configuration when selection is not under test root, e.g. module content root (IDEA-116871) (cherry picked from commit effc865ab3bff89d4651054569ef7ac4f86d7b33)
f8ff71b: product name -> full product name (IDEA-117070) (cherry picked from commit 2b4dc107514b4bd13ec4dced1144c81de79a0bb7)
d60166d: plugins advertiser: ensure that all installed plugins would be enabled - check also unknown plugins (IDEA-117068) (cherry picked from commit 99ffd837ba1ec2523ae8c4faa2060c84b5941986)
b3ed3c2: plugins advertiser: do not suggest to update to ultimate on implicitly disabled plugins (IDEA-117040) (cherry picked from commit e5452974f1a45693dd8ddb967525d37cd54f3ba4)
61ebb02: IDEA-116991 "IDE is up to date" message (cherry picked from commit 094ac76636050b6f0796c9802342cb3d431eeab0)
a4dc3a5: lambda: process lambda as parameter for anonymous class (IDEA-116987) (cherry picked from commit bf64625fb2e79f29f924d47fb68ec55d7c46d954)
7be1ec1: IDEA-117071 (language level in decompiled .class files)
5e5d914: relative path - special url, encoding is not required (cherry picked from commit 58704c7)
7f786c5: cleanup (cherry picked from commit 3868464)
208311d: cleanup (cherry picked from commit d58146c)
53f1175: CR-IC-3246 (cherry picked from commit 5d6a0c8)
a186992: CR-IC-3246 (cherry picked from commit 51864f4)
04cd96d: open in browser — choose url, show full url, not only path (decoded form with parameters) (cherry picked from commit b3fff55)
bb59091: WeightBasedComparator — string natural compare (cherry picked from commit 86971b9)
52c78b1: overrides (cherry picked from commit 716766a)
5b53293: Urls.newFromIdea returns not-null (cherry picked from commit f47f98a)
fde95ae: move Url to platform - avoid raw string (cherry picked from commit d4e4a40)
7dabf92: UriUtil.trimLastSlash refine Url nullability (newFromIdea is not yet done) (cherry picked from commit 9b8aac5)
e1bcebb: CR-IC-2986 (cherry picked from commit 34ef731)
6a65720: cleanup (cherry picked from commit e50df4c)
60e168b: CR-IC-2986 MessageBuilder -> MessageDialogBuilder (cherry picked from commit 1999b51)
be3b2ec: some memory tune-ups
cfbafa0: IDEA-117077 Can't remove files from Recent Files
3f42891: EA-52338 - assert: ComponentManagerImpl.getComponent (cherry picked from commit 7c076b6)
58bc683: IDEA-117030 Groovy/Gradle frequent, severe hangs (cherry picked from commit aadeb26)
0ef7db2: IDEA-117073 Recent files and Switcher are not centred in ide window
4a2dde3: file watchers tips should be in WS only
39ee2d2: update complete statement tips
292b280: remove image tag
bffe81e: missed images
b975e7d: Add missing module definition.
3cd9608: Add license for "aether-api-0.9.0.M2.jar" (cherry picked from commit 0df2a18)
d63a566: IDEA-116452 "Resolve workspace artifacts" option doesn't work with Maven 3.1.x (cherry picked from commit 8c35e68)
9103476: Enter in SE should close popup if selection is a setting
4f37f20: button placed on top, should be in the middle
6c28556: [log] IDEA-116399 Fix filter by branch
7684e66: IDEA-116881 Please time stamp gradle tasks (cherry picked from commit 79c4e6e)
db139a1: IDEA-116891 gradle import creates a lot of extra empty directories (cherry picked from commit 9732da7)
9ed8e39: WEB-9933 What should happen when creating node.js Express App as New Module? (cherry picked from commit a0c7d51) CR-WS-262
2e2fd29: IDEA-116891 gradle import creates a lot of extra empty directories (cherry picked from commit ca7e083)
5902fb8: IDEA-116974 Gradle Plugin doesn't handle 'providedCompile' dependencies in 'war' projects correctly (cherry picked from commit d3f9d06)
0e97c89: Merge remote-tracking branch 'origin/133' into 133
5be1c50: IDEA-115546 Full Screen Mode: main menu persists on screen, when invoked by the keyboard shortcut(reviewed by kb)
4055528: IDEA-111161 Flat tool window design PATCH(reviewed by kb)
17913b8: Lens pixel hunting (reviewed by kb)
38dd8e8: select correct shell runner in title [^Peter]
57befaf: IDEA-116917 check for jansi in classpath [^Peter]
93e3010: IDEA-66494 Switching between search and replace (cherry picked from commit d7dc6ca) [r=Peter.Gromov]
45d852b: IDEA-66494 Switching between search and replace (cherry picked from commit d7dc6ca) [r=Peter.Gromov]
7673aeb: IDEA-116952 IntelliJ LAF issue (set label.disabledForeground to 999999)
56d2cb6: IDEA-116911 Speed search: wrong background in recent files
6ecd960: IDEA-115577 Commit Changes: keyboard shortcut for Commit Message History does not work
27aa855: IDEA-115708 Add workaround by setting global SSLContext (cherry picked from commit fc3f452bbbef193a3ebf6fd28d7e0bffb14a9a5a)
7c3e066: get rid of invoke later [^Peter]
3f10d5b: special icon for 'generated source' roots: added file forgotten by first cherry-pick (cherry picked from commit 35806f22)
6f3780e: grayed text is invisible on Linux
f64ba46: menu is not visible on Linux + IntelliJ theme
e7f0816: [vcs] IDEA-115571 Don't clean change lists's commit message until committed
f0226f9: [log] Make "show details" & "show long edges" actions dumb aware (cherry picked from commit 726ffc1)
8ca08ac: [log] IDEA-116950 Draw just "tag +" instead of "tag + 5 more" (cherry picked from commit 49a033a)
976a8ef: [log] IDEA-116950 Don't display all tags if there are too many of them
4a1db8f: [log] Refactor: move ref painter & drawRefs & calc refs padding to the common parent class (cherry picked from commit 3bb3524)
5dd3597: IDEA-113730 Implemented "cat" command to read content as binary data (not to read as text data and then convert to bytes using some encoding) (cherry picked from commit efd5985)
4201c87: update tips
5c4c6e0: special icon for 'generated source' roots [rev by Peter] (cherry picked from commit 35806f2)
fcc237f: [^nicity] fix outdated javadoc (completion is performed in a read action) (cherry picked from commit d4e5553)
0f918a9: [^nicity] support hippie completion at the file start (EA-52100) (cherry picked from commit 3334c0b)
41b5038: IDEA-102449 Mac OS + JDK 1.7: dialog sheets go to background if focus is moved from IDEA and then back
aff52ee: IDEA-116784 Error Parsing Regex /\s/ in Groovy [^Peter]
8bf0c61: IDEA-95170 closure parameter type [^peter]
8f7c63d: IDEA-116378 only expressions are available in loop conditions [^peter]
d889262: IDEA-116837 Groovy: don't suggest to shorten references in comments [^peter]
f835a08: IDEA-116621 Groovy: Extract Parameter Refactoring: 'Replace this occurrence only' replaces all occurrences in current method [^peter]
6ee4359: [log] fix action's update()
5b8fb93: do not update recent projects on closing in headless mode
3fb3322: Merge remote-tracking branch 'origin/133' into 133
9251d90: SSH console - credentials validation (cherry picked from commit 8b7b23a)
9947162: IDEA-116824 Gradle: Provide an inspection & quickfix for multiple custom maven repo links (cherry picked from commit 810199f)
Change-Id: I47b8e5f8b6b865ec46d5625dd1838900539d7d93
diff --git a/python/IntelliLang-python/src/META-INF/intellilang-python-support.xml b/python/IntelliLang-python/src/META-INF/intellilang-python-support.xml
index 2ffa9f7..ce37b6b 100644
--- a/python/IntelliLang-python/src/META-INF/intellilang-python-support.xml
+++ b/python/IntelliLang-python/src/META-INF/intellilang-python-support.xml
@@ -7,5 +7,8 @@
</extensions>
<extensions defaultExtensionNs="com.intellij">
<patterns.patternClass className="com.jetbrains.python.patterns.PythonPatterns" alias="py"/>
+ <multiHostInjector implementation="com.jetbrains.python.intelliLang.PyCommentInjector"/>
+ <multiHostInjector implementation="com.jetbrains.python.intelliLang.PyConfigurationInjector"/>
+ <multiHostInjector implementation="com.jetbrains.python.intelliLang.PyTemporaryInjector"/>
</extensions>
</idea-plugin>
\ No newline at end of file
diff --git a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyCommentInjector.java b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyCommentInjector.java
new file mode 100644
index 0000000..45eb96b
--- /dev/null
+++ b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyCommentInjector.java
@@ -0,0 +1,25 @@
+package com.jetbrains.python.intelliLang;
+
+import com.intellij.lang.Language;
+import com.intellij.psi.PsiElement;
+import com.jetbrains.python.codeInsight.PyInjectorBase;
+import org.intellij.plugins.intelliLang.inject.InjectedLanguage;
+import org.intellij.plugins.intelliLang.inject.InjectorUtils;
+import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author vlan
+ */
+public class PyCommentInjector extends PyInjectorBase {
+ @Nullable
+ @Override
+ public Language getInjectedLanguage(@NotNull PsiElement context) {
+ final BaseInjection injection = InjectorUtils.findCommentInjection(context, "comment", null);
+ if (injection != null) {
+ return InjectedLanguage.findLanguageById(injection.getInjectedLanguageId());
+ }
+ return null;
+ }
+}
diff --git a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyConfigurationInjector.java b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyConfigurationInjector.java
new file mode 100644
index 0000000..f672f5d
--- /dev/null
+++ b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyConfigurationInjector.java
@@ -0,0 +1,33 @@
+package com.jetbrains.python.intelliLang;
+
+import com.intellij.lang.Language;
+import com.intellij.psi.PsiElement;
+import com.jetbrains.python.codeInsight.PyInjectorBase;
+import org.intellij.plugins.intelliLang.Configuration;
+import org.intellij.plugins.intelliLang.inject.InjectedLanguage;
+import org.intellij.plugins.intelliLang.inject.InjectorUtils;
+import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport;
+import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author vlan
+ */
+public class PyConfigurationInjector extends PyInjectorBase {
+ @Nullable
+ @Override
+ public Language getInjectedLanguage(@NotNull PsiElement context) {
+ for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) {
+ if (support instanceof PyLanguageInjectionSupport) {
+ final Configuration configuration = Configuration.getInstance();
+ for (BaseInjection injection : configuration.getInjections(support.getId())) {
+ if (injection.acceptsPsiElement(context)) {
+ return InjectedLanguage.findLanguageById(injection.getInjectedLanguageId());
+ }
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
index 5a91db5..dee16d2 100644
--- a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
+++ b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
@@ -15,22 +15,17 @@
*/
package com.jetbrains.python.intelliLang;
-import com.intellij.lang.Language;
-import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.jetbrains.python.patterns.PythonPatterns;
import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.psi.PyStringLiteralExpression;
import org.intellij.plugins.intelliLang.inject.AbstractLanguageInjectionSupport;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
-import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.List;
-
/**
* @author yole
*/
@@ -54,36 +49,15 @@
return host instanceof PyElement;
}
- @Override
- public boolean useDefaultInjector(PsiLanguageInjectionHost host) {
- return true;
- }
-
- @Override
- public BaseInjection createInjection(Element element) {
- // This is how DefaultLanguageInjector gets its injection ranges
- return new BaseInjection(getId()) {
- @NotNull
- @Override
- public List<TextRange> getInjectedArea(PsiElement element) {
- if (element instanceof PyStringLiteralExpression) {
- return ((PyStringLiteralExpression)element).getStringValueTextRanges();
- }
- return super.getInjectedArea(element);
- }
- };
- }
-
- @Override
- public boolean addInjectionInPlace(Language language, PsiLanguageInjectionHost psiElement) {
- // XXX: Disable temporary injections via intention actions for Python elements, since TemporaryPlacesInjector cannot handle elements
- // with multiple injection text ranges (PY-10691)
- return true;
- }
-
@Nullable
@Override
public String getHelpId() {
return "reference.settings.language.injection.generic.python";
}
+
+ @Nullable
+ @Override
+ public BaseInjection findCommentInjection(@NotNull PsiElement host, @Nullable Ref<PsiElement> commentRef) {
+ return null;
+ }
}
diff --git a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyTemporaryInjector.java b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyTemporaryInjector.java
new file mode 100644
index 0000000..0bbcdef
--- /dev/null
+++ b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyTemporaryInjector.java
@@ -0,0 +1,40 @@
+package com.jetbrains.python.intelliLang;
+
+import com.intellij.lang.Language;
+import com.intellij.lang.injection.MultiHostRegistrar;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiLanguageInjectionHost;
+import com.jetbrains.python.codeInsight.PyInjectorBase;
+import org.intellij.plugins.intelliLang.inject.InjectedLanguage;
+import org.intellij.plugins.intelliLang.inject.InjectorUtils;
+import org.intellij.plugins.intelliLang.inject.TemporaryPlacesRegistry;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author vlan
+ */
+public class PyTemporaryInjector extends PyInjectorBase {
+ @Override
+ public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
+ if (registerInjection(registrar, context)) {
+ final TemporaryPlacesRegistry registry = TemporaryPlacesRegistry.getInstance(context.getProject());
+ InjectorUtils.registerSupport(registry.getLanguageInjectionSupport(), false, registrar);
+ }
+ }
+
+ @Nullable
+ @Override
+ public Language getInjectedLanguage(@NotNull PsiElement context) {
+ final TemporaryPlacesRegistry registry = TemporaryPlacesRegistry.getInstance(context.getProject());
+ if (context instanceof PsiLanguageInjectionHost) {
+ final PsiFile file = context.getContainingFile();
+ final InjectedLanguage injectedLanguage = registry.getLanguageFor((PsiLanguageInjectionHost)context, file);
+ if (injectedLanguage != null) {
+ return injectedLanguage.getLanguage();
+ }
+ }
+ return null;
+ }
+}
diff --git a/python/IntelliLang-python/src/pyInjections.xml b/python/IntelliLang-python/src/pyInjections.xml
index e9ae34e..f561c1d 100644
--- a/python/IntelliLang-python/src/pyInjections.xml
+++ b/python/IntelliLang-python/src/pyInjections.xml
@@ -9,6 +9,6 @@
</injection>
<injection language="SQL" injector-id="python">
<display-name>"SQL select/delete/insert/update/create"</display-name>
- <place><![CDATA[pyLiteralExpression().withText(string().matchesBrics(" *(((SELECT|DELETE) .*FROM)|((INSERT|REPLACE) .*INTO)|(UPDATE .* SET)|((CREATE|DROP|ALTER) +(TABLE|INDEX))) .*"))]]></place>
+ <place><![CDATA[pyLiteralExpression().withText(string().matchesBrics("[UuRrBb\\\"\\' \t]*(((SELECT|DELETE) .*FROM)|((INSERT|REPLACE) .*INTO)|(UPDATE .* SET)|((CREATE|DROP|ALTER) +(TABLE|INDEX))) .*"))]]></place>
</injection>
</component>
diff --git a/python/helpers/generator3.py b/python/helpers/generator3.py
index 5fced92..fe24620 100644
--- a/python/helpers/generator3.py
+++ b/python/helpers/generator3.py
@@ -38,12 +38,12 @@
return fname
-def redo_module(mod_name, outfile, module_file_name, doing_builtins):
+def redo_module(module_name, outfile, module_file_name, doing_builtins):
# gobject does 'del _gobject' in its __init__.py, so the chained attribute lookup code
# fails to find 'gobject._gobject'. thus we need to pull the module directly out of
# sys.modules
- mod = sys.modules.get(mod_name)
- mod_path = mod_name.split('.')
+ mod = sys.modules.get(module_name)
+ mod_path = module_name.split('.')
if not mod and sys.platform == 'cli':
# "import System.Collections" in IronPython 2.7 doesn't actually put System.Collections in sys.modules
# instead, sys.modules['System'] get set to a Microsoft.Scripting.Actions.NamespaceTracker and Collections can be
@@ -54,16 +54,16 @@
mod = getattr(mod, component)
except AttributeError:
mod = None
- report("Failed to find CLR module " + mod_name)
+ report("Failed to find CLR module " + module_name)
break
if mod:
action("restoring")
r = ModuleRedeclarator(mod, outfile, module_file_name, doing_builtins=doing_builtins)
- r.redo(mod_name, ".".join(mod_path[:-1]) in MODULES_INSPECT_DIR)
+ r.redo(module_name, ".".join(mod_path[:-1]) in MODULES_INSPECT_DIR)
action("flushing")
r.flush()
else:
- report("Failed to find imported module in sys.modules " + mod_name)
+ report("Failed to find imported module in sys.modules " + module_name)
# find_binaries functionality
def cut_binary_lib_suffix(path, f):
@@ -122,6 +122,18 @@
os.path.exists(os.path.join(root, d, "__init__.pyo")))
+def walk_python_path(path):
+ for root, dirs, files in os.walk(path):
+ if root.endswith('__pycache__'):
+ continue
+ dirs_copy = list(dirs)
+ for d in dirs_copy:
+ if d.endswith('__pycache__') or not is_module(d, root):
+ dirs.remove(d)
+ # some files show up but are actually non-existent symlinks
+ yield root, [f for f in files if os.path.exists(os.path.join(root, f))]
+
+
def list_binaries(paths):
"""
Finds binaries in the given list of paths.
@@ -139,13 +151,7 @@
paths = sorted_no_case(paths)
for path in paths:
if path == os.path.dirname(sys.argv[0]): continue
- for root, dirs, files in os.walk(path):
- if root.endswith('__pycache__'): continue
- dirs_copy = list(dirs)
- for d in dirs_copy:
- if d.endswith("__pycache__") or not is_module(d, root):
- dirs.remove(d)
-
+ for root, files in walk_python_path(path):
cutpoint = path.rfind(SEP)
if cutpoint > 0:
preprefix = path[(cutpoint + len(SEP)):] + '.'
@@ -180,17 +186,10 @@
path = os.path.normpath(path)
- for root, dirs, files in os.walk(path):
- if root.endswith('__pycache__'): continue
- dirs_copy = list(dirs)
- for d in dirs_copy:
- if d.endswith("__pycache__") or not is_module(d, root):
- dirs.remove(d)
+ for root, files in walk_python_path(path):
for name in files:
if name.endswith('.py'):
file_path = os.path.join(root, name)
- # some files show up but are actually non-existent symlinks
- if not os.path.exists(file_path): continue
say("%s\t%s\t%d", os.path.normpath(file_path), path, os.path.getsize(file_path))
say('END')
sys.stdout.flush()
diff --git a/python/helpers/pycharm/tcunittest.py b/python/helpers/pycharm/tcunittest.py
index 07da02d..b6950c9 100644
--- a/python/helpers/pycharm/tcunittest.py
+++ b/python/helpers/pycharm/tcunittest.py
@@ -47,7 +47,7 @@
quot = val[0]
count = 1
quote_ind = val[count:].find(quot)
- while val[count+quote_ind-1] == "\\" and quote_ind != -1:
+ while quote_ind != -1 and val[count+quote_ind-1] == "\\":
count = count + quote_ind + 1
quote_ind = val[count:].find(quot)
@@ -60,16 +60,15 @@
val = val[val_index+2:].strip()
quot = val[0]
quote_ind = val[count:].find(quot)
- while val[count+quote_ind-1] == "\\" and quote_ind != -1:
+ while quote_ind != -1 and val[count+quote_ind-1] == "\\":
count = count + quote_ind + 1
quote_ind = val[count:].find(quot)
return val[0:quote_ind+count+1]
else:
quot = val[-1]
- count = 0
- quote_ind = val[:len(val)-count-1].rfind(quot)
- while val[quote_ind-1] == "\\":
+ quote_ind = val[:len(val)-1].rfind(quot)
+ while quote_ind != -1 and val[quote_ind-1] == "\\":
quote_ind = val[:quote_ind-1].rfind(quot)
return val[quote_ind:]
diff --git a/python/helpers/pydev/pydev_console_utils.py b/python/helpers/pydev/pydev_console_utils.py
index ee62910..54a8585 100644
--- a/python/helpers/pydev/pydev_console_utils.py
+++ b/python/helpers/pydev/pydev_console_utils.py
@@ -4,6 +4,7 @@
import traceback
from pydevd_constants import USE_LIB_COPY
+from pydevd_constants import IS_JYTHON
try:
if USE_LIB_COPY:
@@ -132,6 +133,16 @@
return '\n'
+class CodeFragment:
+ def __init__(self, text, is_single_line=True):
+ self.text = text
+ self.is_single_line = is_single_line
+
+ def append(self, code_fragment):
+ self.text = self.text + "\n" + code_fragment.text
+ if not code_fragment.is_single_line:
+ self.is_single_line = False
+
#=======================================================================================================================
# BaseInterpreterInterface
#=======================================================================================================================
@@ -140,22 +151,16 @@
self.mainThread = mainThread
self.interruptable = False
self.exec_queue = _queue.Queue(0)
- self.buffer = []
+ self.buffer = None
- def needMore(self, buffer, line):
- if not buffer:
- buffer = []
- buffer.append(line)
- source = "\n".join(buffer)
+ def needMoreForCode(self, source):
if hasattr(self.interpreter, 'is_complete'):
return not self.interpreter.is_complete(source)
-
try:
- code = self.interpreter.compile(source, "<input>", "single")
+ code = self.interpreter.compile(source, '<input>', 'exec')
except (OverflowError, SyntaxError, ValueError):
# Case 1
return False
-
if code is None:
# Case 2
return True
@@ -163,10 +168,15 @@
# Case 3
return False
+ def needMore(self, code_fragment):
+ if self.buffer is None:
+ self.buffer = code_fragment
+ else:
+ self.buffer.append(code_fragment)
+
+ return self.needMoreForCode(self.buffer.text)
- def addExec(self, line):
- #f_opened = open('c:/temp/a.txt', 'a')
- #f_opened.write(line+'\n')
+ def addExec(self, code_fragment):
original_in = sys.stdin
try:
help = None
@@ -199,14 +209,14 @@
self._input_error_printed = True
sys.stderr.write('\nError when trying to update pydoc.help.input\n')
sys.stderr.write('(help() may not work -- please report this as a bug in the pydev bugtracker).\n\n')
- import traceback;
+ import traceback
traceback.print_exc()
try:
self.startExec()
- more = self.doAddExec(line)
- self.finishExec()
+ more = self.doAddExec(code_fragment)
+ self.finishExec(more)
finally:
if help is not None:
try:
@@ -226,12 +236,10 @@
traceback.print_exc()
- #it's always false at this point
- need_input = False
- return more, need_input
+ return more
- def doAddExec(self, line):
+ def doAddExec(self, codeFragment):
'''
Subclasses should override.
@@ -309,15 +317,31 @@
return ''
- def execLine(self, line):
+ def doExecCode(self, code, is_single_line):
try:
- #buffer = self.interpreter.buffer[:]
- self.exec_queue.put(line)
- return self.needMore(self.buffer, line)
+ code_fragment = CodeFragment(code, is_single_line)
+ more = self.needMore(code_fragment)
+ if not more:
+ code_fragment = self.buffer
+ self.buffer = None
+ self.exec_queue.put(code_fragment)
+
+ return more
except:
traceback.print_exc()
return False
+ def execLine(self, line):
+ return self.doExecCode(line, True)
+
+
+ def execMultipleLines(self, lines):
+ if IS_JYTHON:
+ for line in lines.split('\n'):
+ self.doExecCode(line, True)
+ else:
+ return self.doExecCode(lines, False)
+
def interrupt(self):
try:
@@ -343,13 +367,13 @@
else:
return None
- def finishExec(self):
+ def finishExec(self, more):
self.interruptable = False
server = self.get_server()
if server is not None:
- return server.NotifyFinished()
+ return server.NotifyFinished(more)
else:
return True
diff --git a/python/helpers/pydev/pydev_ipython_console.py b/python/helpers/pydev/pydev_ipython_console.py
index d3d4ae8..6a8e056 100644
--- a/python/helpers/pydev/pydev_ipython_console.py
+++ b/python/helpers/pydev/pydev_ipython_console.py
@@ -39,14 +39,14 @@
def get_greeting_msg(self):
return self.interpreter.get_greeting_msg()
- def doAddExec(self, line):
+ def doAddExec(self, codeFragment):
self.notify_about_magic()
- if (line.rstrip().endswith('??')):
+ if (codeFragment.text.rstrip().endswith('??')):
print('IPython-->')
try:
- res = bool(self.interpreter.addExec(line))
+ res = bool(self.interpreter.addExec(codeFragment.text))
finally:
- if (line.rstrip().endswith('??')):
+ if (codeFragment.text.rstrip().endswith('??')):
print('<--IPython')
return res
diff --git a/python/helpers/pydev/pydev_monkey.py b/python/helpers/pydev/pydev_monkey.py
index 07c7e2b..8dd94ab 100644
--- a/python/helpers/pydev/pydev_monkey.py
+++ b/python/helpers/pydev/pydev_monkey.py
@@ -37,8 +37,9 @@
host, port = pydevd.dispatch()
if port is not None:
- args[indC + 1] = "import sys; sys.path.append('%s'); import pydevd; pydevd.settrace(host='%s', port=%s, suspend=False); %s"%(helpers, host, port, args[indC + 1])
- return args
+ new_args.extend(args)
+ new_args[indC + 1] = "import sys; sys.path.append('%s'); import pydevd; pydevd.settrace(host='%s', port=%s, suspend=False); %s"%(helpers, host, port, args[indC + 1])
+ return new_args
else:
new_args.append(args[0])
else:
@@ -99,8 +100,9 @@
args = str_to_args(new_arg_str)
if not is_python(args[0]):
return arg_str
- art = args_to_str(patch_args(args))
- return art
+ arg_str = args_to_str(patch_args(args))
+ pydev_log.debug("New args: %s"% arg_str)
+ return arg_str
def monkey_patch_module(module, funcname, create_func):
if hasattr(module, funcname):
diff --git a/python/helpers/pydev/pydevconsole.py b/python/helpers/pydev/pydevconsole.py
index 026fb7f..e8b8d29 100644
--- a/python/helpers/pydev/pydevconsole.py
+++ b/python/helpers/pydev/pydevconsole.py
@@ -10,7 +10,7 @@
import sys
from pydevd_constants import USE_LIB_COPY
-from pydevd_utils import *
+from pydevd_constants import IS_JYTHON
if USE_LIB_COPY:
import _pydev_threading as threading
@@ -51,6 +51,7 @@
setattr(__builtin__, 'False', 0)
from pydev_console_utils import BaseInterpreterInterface
+from pydev_console_utils import CodeFragment
IS_PYTHON_3K = False
@@ -72,56 +73,30 @@
except ImportError:
import _pydev_xmlrpclib as xmlrpclib
-try:
- class ExecState:
- FIRST_CALL = True
- PYDEV_CONSOLE_RUN_IN_UI = False #Defines if we should run commands in the UI thread.
- from org.python.pydev.core.uiutils import RunInUiThread #@UnresolvedImport
- from java.lang import Runnable #@UnresolvedImport
+class Command:
+ def __init__(self, interpreter, code_fragment):
+ """
+ :type code_fragment: CodeFragment
+ :type interpreter: InteractiveConsole
+ """
+ self.interpreter = interpreter
+ self.code_fragment = code_fragment
+ self.more = None
- class Command(Runnable):
- def __init__(self, interpreter, line):
- self.interpreter = interpreter
- self.line = line
-
- def run(self):
- if ExecState.FIRST_CALL:
- ExecState.FIRST_CALL = False
- sys.stdout.write('\nYou are now in a console within Eclipse.\nUse it with care as it can halt the VM.\n')
- sys.stdout.write(
- 'Typing a line with "PYDEV_CONSOLE_TOGGLE_RUN_IN_UI"\nwill start executing all the commands in the UI thread.\n\n')
-
- if self.line == 'PYDEV_CONSOLE_TOGGLE_RUN_IN_UI':
- ExecState.PYDEV_CONSOLE_RUN_IN_UI = not ExecState.PYDEV_CONSOLE_RUN_IN_UI
- if ExecState.PYDEV_CONSOLE_RUN_IN_UI:
- sys.stdout.write(
- 'Running commands in UI mode. WARNING: using sys.stdin (i.e.: calling raw_input()) WILL HALT ECLIPSE.\n')
- else:
- sys.stdout.write('No longer running commands in UI mode.\n')
- self.more = False
- else:
- self.more = self.interpreter.push(self.line)
-
-
- def Sync(runnable):
- if ExecState.PYDEV_CONSOLE_RUN_IN_UI:
- return RunInUiThread.sync(runnable)
+ @staticmethod
+ def symbol_for_fragment(code_fragment):
+ if code_fragment.is_single_line:
+ symbol = 'single'
else:
- return runnable.run()
+ symbol = 'exec' # Jython doesn't support this
+ return symbol
-except:
- #If things are not there, define a way in which there's no 'real' sync, only the default execution.
- class Command:
- def __init__(self, interpreter, line):
- self.interpreter = interpreter
- self.line = line
+ def run(self):
+ text = self.code_fragment.text
+ symbol = self.symbol_for_fragment(self.code_fragment)
- def run(self):
- self.more = self.interpreter.push(self.line)
-
- def Sync(runnable):
- runnable.run()
+ self.more = self.interpreter.runsource(text, '<input>', symbol)
try:
try:
@@ -152,9 +127,9 @@
self._input_error_printed = False
- def doAddExec(self, line):
- command = Command(self.interpreter, line)
- Sync(command)
+ def doAddExec(self, codeFragment):
+ command = Command(self.interpreter, codeFragment)
+ command.run()
return command.more
@@ -185,14 +160,13 @@
while 1:
try:
try:
- line = interpreter.exec_queue.get(block=True, timeout=0.05)
+ codeFragment = interpreter.exec_queue.get(block=True, timeout=0.05)
except _queue.Empty:
continue
- if not interpreter.addExec(line): #TODO: think about locks here
- interpreter.buffer = []
+ more = interpreter.addExec(codeFragment)
except KeyboardInterrupt:
- interpreter.buffer = []
+ interpreter.buffer = None
continue
except SystemExit:
raise
@@ -274,6 +248,7 @@
raise
server.register_function(interpreter.execLine)
+ server.register_function(interpreter.execMultipleLines)
server.register_function(interpreter.getCompletions)
server.register_function(interpreter.getFrame)
server.register_function(interpreter.getVariable)
@@ -339,17 +314,17 @@
def get_frame():
return interpreterInterface.getFrame()
-def exec_expression(expression, globals, locals):
+def exec_code(code, globals, locals):
interpreterInterface = get_interpreter()
interpreterInterface.interpreter.update(globals, locals)
- res = interpreterInterface.needMore(None, expression)
+ res = interpreterInterface.needMore(code)
if res:
return True
- interpreterInterface.addExec(expression)
+ interpreterInterface.addExec(code)
return False
@@ -399,7 +374,7 @@
updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals
if IPYTHON:
- return exec_expression(expression, updated_globals, frame.f_locals)
+ return exec_code(CodeFragment(expression), updated_globals, frame.f_locals)
interpreter = ConsoleWriter()
diff --git a/python/helpers/pydev/pydevd_constants.py b/python/helpers/pydev/pydevd_constants.py
index 34759f7..5e78e15 100644
--- a/python/helpers/pydev/pydevd_constants.py
+++ b/python/helpers/pydev/pydevd_constants.py
@@ -41,6 +41,10 @@
import os
+import pydevd_vm_type
+
+IS_JYTHON = pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON
+
#=======================================================================================================================
# Python 3?
#=======================================================================================================================
diff --git a/python/helpers/pydev/test_debug.py b/python/helpers/pydev/test_debug.py
index 89051c8..bc55de1 100644
--- a/python/helpers/pydev/test_debug.py
+++ b/python/helpers/pydev/test_debug.py
@@ -1,16 +1,20 @@
__author__ = 'Dmitry.Trofimov'
import unittest
+import os
+
+test_data_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..', '..', 'python', 'testData', 'debug'))
class PyDevTestCase(unittest.TestCase):
def testZipFileExits(self):
from pydevd_file_utils import exists
- self.assertTrue(exists('../../../testData/debug/zipped_lib.zip/zipped_module.py'))
- self.assertFalse(exists('../../../testData/debug/zipped_lib.zip/zipped_module2.py'))
- self.assertFalse(exists('../../../testData/debug/zipped_lib2.zip/zipped_module.py'))
+
+ self.assertTrue(exists(test_data_path +'/zipped_lib.zip/zipped_module.py'))
+ self.assertFalse(exists(test_data_path + '/zipped_lib.zip/zipped_module2.py'))
+ self.assertFalse(exists(test_data_path + '/zipped_lib2.zip/zipped_module.py'))
def testEggFileExits(self):
from pydevd_file_utils import exists
- self.assertTrue(exists('../../../testData/debug/pycharm-debug.egg/pydev/pydevd.py'))
- self.assertFalse(exists('../../../testData/debug/pycharm-debug.egg/pydev/pydevd2.py'))
+ self.assertTrue(exists(test_data_path + '/pycharm-debug.egg/pydev/pydevd.py'))
+ self.assertFalse(exists(test_data_path + '/pycharm-debug.egg/pydev/pydevd2.py'))
diff --git a/python/openapi/src/com/jetbrains/python/psi/PyStringLiteralFileReferenceSet.java b/python/openapi/src/com/jetbrains/python/psi/PyStringLiteralFileReferenceSet.java
index e74cd80..6c470c7 100644
--- a/python/openapi/src/com/jetbrains/python/psi/PyStringLiteralFileReferenceSet.java
+++ b/python/openapi/src/com/jetbrains/python/psi/PyStringLiteralFileReferenceSet.java
@@ -20,17 +20,19 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiReferenceProvider;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
-import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* @author traff
*/
public class PyStringLiteralFileReferenceSet extends RootFileReferenceSet {
+ public static final Pattern DELIMITERS = Pattern.compile("\\\\|/");
private final PyStringLiteralExpression myStringLiteralExpression;
@@ -57,61 +59,33 @@
protected void reparse() {
//noinspection ConstantConditions
if (myStringLiteralExpression != null) {
- MyTextRangeConsumer textRangeConsumer = new MyTextRangeConsumer(this);
-
- myStringLiteralExpression.iterateCharacterRanges(textRangeConsumer);
- textRangeConsumer.finish();
-
- List<FileReference> referencesList = textRangeConsumer.myReferenceList;
-
- myReferences = referencesList.toArray(new FileReference[referencesList.size()]);
+ final List<FileReference> references = getFileReferences(myStringLiteralExpression);
+ myReferences = references.toArray(new FileReference[references.size()]);
}
}
- private static class MyTextRangeConsumer implements PyStringLiteralExpression.TextRangeConsumer {
- private final StringBuilder myItem = new StringBuilder();
- private int myStartOffset = -1;
- private int myIndex = 0;
- private int myEndOffset = -1;
- private final FileReferenceSet myFileReferenceSet;
-
-
- private final List<FileReference> myReferenceList = new ArrayList<FileReference>();
-
- private MyTextRangeConsumer(FileReferenceSet set) {
- myFileReferenceSet = set;
- }
-
- @Override
- public boolean process(int startOffset, int endOffset, String value) {
- if ("\\".equals(value) || "/".equals(value)) {
- addReference(startOffset);
+ @NotNull
+ private List<FileReference> getFileReferences(@NotNull PyStringLiteralExpression expression) {
+ final String value = expression.getStringValue();
+ final Matcher matcher = DELIMITERS.matcher(value);
+ int start = 0;
+ int index = 0;
+ final List<FileReference> results = new ArrayList<FileReference>();
+ while (matcher.find()) {
+ final String s = value.substring(start, matcher.start());
+ if (!s.isEmpty()) {
+ final TextRange range = TextRange.create(expression.valueOffsetToTextOffset(start),
+ expression.valueOffsetToTextOffset(matcher.start()));
+ results.add(createFileReference(range, index++, s));
}
- else {
- if (myStartOffset == -1) {
- myStartOffset = startOffset;
- }
- myEndOffset = endOffset;
- myItem.append(value);
- }
- return true;
+ start = matcher.end();
}
-
- private void addReference(int startOffset) {
- if (myStartOffset != -1) {
- final FileReference ref = myFileReferenceSet.createFileReference(
- new TextRange(myStartOffset, startOffset),
- myIndex++,
- myItem.toString());
- myReferenceList.add(ref);
- myStartOffset = -1;
- myItem.setLength(0);
- }
+ final String s = value.substring(start);
+ if (!s.isEmpty()) {
+ final TextRange range = TextRange.create(expression.valueOffsetToTextOffset(start),
+ expression.valueOffsetToTextOffset(value.length()));
+ results.add(createFileReference(range, index, s));
}
-
-
- public void finish() {
- addReference(myEndOffset);
- }
+ return results;
}
}
diff --git a/python/pluginResources/META-INF/plugin.xml b/python/pluginResources/META-INF/plugin.xml
index 0d0d760..f263de7 100644
--- a/python/pluginResources/META-INF/plugin.xml
+++ b/python/pluginResources/META-INF/plugin.xml
@@ -4,9 +4,9 @@
<id>PythonCore</id>
<name>Python Community Edition</name>
- <idea-version since-build="130.0" until-build="133.*"/>
+ <idea-version since-build="133.286" until-build="133.*"/>
<description>Smart editing for Python scripts</description>
- <version>3.1 Beta</version>
+ <version>3.1 Beta 2</version>
<depends>com.intellij.modules.java</depends>
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyStringLiteralExpression.java b/python/psi-api/src/com/jetbrains/python/psi/PyStringLiteralExpression.java
index 8c3182d..f7dd122 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyStringLiteralExpression.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyStringLiteralExpression.java
@@ -16,8 +16,10 @@
package com.jetbrains.python.psi;
import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiLanguageInjectionHost;
+import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -28,20 +30,6 @@
int valueOffsetToTextOffset(int valueOffset);
- void iterateCharacterRanges(TextRangeConsumer consumer);
-
- /**
- * Iterator over decoded string characters.
- */
- interface TextRangeConsumer {
- /**
- * Process a decoded character.
- *
- * @param startOffset start offset in the un-decoded string
- * @param endOffset end offset in the un-decoded string
- * @param value decoded character value
- * @return false in order to stop iteration
- */
- boolean process(int startOffset, int endOffset, String value);
- }
+ @NotNull
+ List<Pair<TextRange, String>> getDecodedFragments();
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyResolveResultRater.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyResolveResultRater.java
new file mode 100644
index 0000000..961293f
--- /dev/null
+++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyResolveResultRater.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.psi.impl;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+public interface PyResolveResultRater {
+ ExtensionPointName<PyResolveResultRater> EP_NAME = ExtensionPointName.create("Pythonid.resolveResultRater");
+
+ int getRate(@NotNull final PsiElement target);
+}
diff --git a/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractConsoleCommunication.java b/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractConsoleCommunication.java
index 70594f9..e8fa271 100644
--- a/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractConsoleCommunication.java
+++ b/python/pydevSrc/com/jetbrains/python/console/pydev/AbstractConsoleCommunication.java
@@ -57,9 +57,9 @@
}
@Override
- public void notifyCommandExecuted() {
+ public void notifyCommandExecuted(boolean more) {
for (ConsoleCommunicationListener listener: communicationListeners) {
- listener.commandExecuted();
+ listener.commandExecuted(more);
}
}
diff --git a/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunication.java b/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunication.java
index a114c2c..3017171 100644
--- a/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunication.java
+++ b/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunication.java
@@ -18,13 +18,30 @@
boolean isExecuting();
- void execInterpreter(String s, Function<InterpreterResponse, Object> callback);
+ void execInterpreter(ConsoleCodeFragment code, Function<InterpreterResponse, Object> callback);
void interrupt();
void addCommunicationListener(ConsoleCommunicationListener listener);
- void notifyCommandExecuted();
+ void notifyCommandExecuted(boolean more);
void notifyInputRequested();
+ class ConsoleCodeFragment {
+ private final String myText;
+ private final boolean myIsSingleLine;
+
+ public ConsoleCodeFragment(String text, boolean isSingleLine) {
+ myText = text;
+ myIsSingleLine = isSingleLine;
+ }
+
+ public String getText() {
+ return myText;
+ }
+
+ public boolean isSingleLine() {
+ return myIsSingleLine;
+ }
+ }
}
diff --git a/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunicationListener.java b/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunicationListener.java
index 562f729..a9263b7 100644
--- a/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunicationListener.java
+++ b/python/pydevSrc/com/jetbrains/python/console/pydev/ConsoleCommunicationListener.java
@@ -4,6 +4,6 @@
* @author traff
*/
public interface ConsoleCommunicationListener {
- void commandExecuted();
+ void commandExecuted(boolean more);
void inputRequested();
}
diff --git a/python/pydevSrc/com/jetbrains/python/console/pydev/IScriptConsoleCommunication.java b/python/pydevSrc/com/jetbrains/python/console/pydev/IScriptConsoleCommunication.java
deleted file mode 100644
index 3c998c8..0000000
--- a/python/pydevSrc/com/jetbrains/python/console/pydev/IScriptConsoleCommunication.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2007 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
-
- *******************************************************************************/
-package com.jetbrains.python.console.pydev;
-
-import com.intellij.util.Function;
-
-/**
- * Interface for the console communication.
- *
- * This interface is meant to be the way to communicate with the shell.
- */
-public interface IScriptConsoleCommunication {
-
- /**
- * Executes a given command in the interpreter (push a line)
- *
- * @param command the command to be executed
- * @return the response from the interpreter (contains the stdout, stderr, etc).
- * @throws Exception
- */
- void execInterpreter(String command, Function<InterpreterResponse, Object> onResponseReceived);
-
- /**
- * Creates the completions to be applied in the interpreter.
- *
- * @param text the text with what should be completed (e.g.: xxx.bar.foo)
- * @param offset the offset where the completion was requested in the console document
- * @return a list of proposals that can be applied for the given text.
- * @throws Exception
- */
- //public ICompletionProposal[] getCompletions(String text, int offset) throws Exception;
-
- /**
- * Gets the description to be shown on hover to the user
- *
- * @param text the text representing the completion to be applied
- * @return the description to be shown to the user
- * @throws Exception
- */
- String getDescription(String text) throws Exception;
-
- /**
- * Stops the communication with the server. Should ask the server to terminate at this point.
- * @throws Exception
- */
- void close();
-}
\ No newline at end of file
diff --git a/python/resources/idea/PyCharmCoreApplicationInfo.xml b/python/resources/idea/PyCharmCoreApplicationInfo.xml
index ef906b0..0ac5772 100644
--- a/python/resources/idea/PyCharmCoreApplicationInfo.xml
+++ b/python/resources/idea/PyCharmCoreApplicationInfo.xml
@@ -1,6 +1,6 @@
<component>
<company name="JetBrains s.r.o." url="http://www.jetbrains.com/?fromIDE"/>
- <version major="3" minor="0" eap="true"/>
+ <version major="3" minor="1" eap="true"/>
<build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
<logo url="/pycharm_core_logo.png" textcolor="ffffff" progressColor="ffaa16" progressY="230" progressTailIcon="/community_progress_tail.png"/>
<about url="/pycharm_core_about.png" logoX="300" logoY="265" logoW="75" logoH="30" foreground="ffffff" linkColor="fca11a"/>
diff --git a/python/rest/resources/META-INF/plugin.xml b/python/rest/resources/META-INF/plugin.xml
index 06cd1f4..76e5727 100644
--- a/python/rest/resources/META-INF/plugin.xml
+++ b/python/rest/resources/META-INF/plugin.xml
@@ -3,12 +3,16 @@
<id>org.jetbrains.plugins.rest</id>
<description>This plugin enables support for reStructuredText files (*.rst)</description>
<vendor>JetBrains</vendor>
- <version>132.SNAPSHOT</version>
- <idea-version since-build="130.1" until-build="133.0"/>
+ <version>134.SNAPSHOT</version>
+ <idea-version since-build="130.1"/>
<depends>com.intellij.modules.lang</depends>
<xi:include href="/META-INF/rest.xml" xpointer="xpointer(/idea-plugin/*)"/>
-
+ <change-notes><![CDATA[
+ <ul>
+ <li>Added inspection for title & underline length math (PY-10998)</li>
+ </ul>
+]]></change-notes>
<extensions defaultExtensionNs="com.intellij">
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
</extensions>
diff --git a/python/rest/src/com/jetbrains/rest/RestBundle.properties b/python/rest/src/com/jetbrains/rest/RestBundle.properties
index 24b98c7..192f443 100644
--- a/python/rest/src/com/jetbrains/rest/RestBundle.properties
+++ b/python/rest/src/com/jetbrains/rest/RestBundle.properties
@@ -9,6 +9,7 @@
### Annotators ###
ANN.unknown.target=Unknown target name ''{0}''
ANN.duplicate.target=Duplicate explicit target name ''{0}''
+ANN.title.length=Title length must match the underline
ANN.unusable.anonymous.target=Anonymous hyperlink target has no reference
ANN.inline.block=Blank line is required after a literal block
diff --git a/python/rest/src/com/jetbrains/rest/RestLanguage.java b/python/rest/src/com/jetbrains/rest/RestLanguage.java
index c451e37..df05659 100644
--- a/python/rest/src/com/jetbrains/rest/RestLanguage.java
+++ b/python/rest/src/com/jetbrains/rest/RestLanguage.java
@@ -17,10 +17,7 @@
import com.intellij.lang.Language;
import com.intellij.psi.templateLanguages.TemplateLanguage;
-import com.jetbrains.rest.validation.RestAnnotator;
-import com.jetbrains.rest.validation.RestHyperlinksAnnotator;
-import com.jetbrains.rest.validation.RestInlineBlockAnnotator;
-import com.jetbrains.rest.validation.RestReferenceTargetAnnotator;
+import com.jetbrains.rest.validation.*;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
@@ -48,6 +45,7 @@
_annotators.add(RestHyperlinksAnnotator.class);
_annotators.add(RestReferenceTargetAnnotator.class);
_annotators.add(RestInlineBlockAnnotator.class);
+ _annotators.add(RestTitleAnnotator.class);
}
public Set<Class<? extends RestAnnotator>> getAnnotators() {
diff --git a/python/rest/src/com/jetbrains/rest/psi/RestTitle.java b/python/rest/src/com/jetbrains/rest/psi/RestTitle.java
index eb93cbe..05c2e66 100644
--- a/python/rest/src/com/jetbrains/rest/psi/RestTitle.java
+++ b/python/rest/src/com/jetbrains/rest/psi/RestTitle.java
@@ -16,6 +16,7 @@
package com.jetbrains.rest.psi;
import com.intellij.lang.ASTNode;
+import com.jetbrains.rest.validation.RestElementVisitor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,15 +38,13 @@
@Nullable
public String getName() {
- final String text = getNode().getText();
- if (text.length() == 0) return null;
+ final String text = getNode().getText().trim();
+ if (text.length() < 2) return null;
final char adorn = text.charAt(text.length()-2);
final CharacterIterator it = new StringCharacterIterator(text);
int finish = 0;
for (char ch = it.last(); ch != CharacterIterator.DONE; ch = it.previous()) {
- if (finish == 0)
- finish++;
- else if (ch != adorn) {
+ if (ch != adorn) {
finish = it.getIndex();
break;
}
@@ -63,4 +62,25 @@
return null;
return text.substring(start, finish).trim();
}
+
+ @Nullable
+ public String getUnderline() {
+ final String text = getNode().getText().trim();
+ if (text.length() < 2) return null;
+ final char adorn = text.charAt(text.length()-2);
+ final CharacterIterator it = new StringCharacterIterator(text);
+ int start = 0;
+ for (char ch = it.last(); ch != CharacterIterator.DONE; ch = it.previous()) {
+ if (ch != adorn) {
+ start = it.getIndex() + 1;
+ break;
+ }
+ }
+ return text.substring(start, text.length());
+ }
+
+ @Override
+ protected void acceptRestVisitor(RestElementVisitor visitor) {
+ visitor.visitTitle(this);
+ }
}
diff --git a/python/rest/src/com/jetbrains/rest/validation/RestTitleAnnotator.java b/python/rest/src/com/jetbrains/rest/validation/RestTitleAnnotator.java
new file mode 100644
index 0000000..c906e31
--- /dev/null
+++ b/python/rest/src/com/jetbrains/rest/validation/RestTitleAnnotator.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.rest.validation;
+
+import com.jetbrains.rest.RestBundle;
+import com.jetbrains.rest.psi.RestTitle;
+
+public class RestTitleAnnotator extends RestAnnotator {
+ @Override
+ public void visitTitle(final RestTitle node) {
+ final String name = node.getName();
+ if (name == null) return;
+ int nameLen = name.length();
+ final String underline = node.getUnderline();
+ if (underline != null && nameLen != underline.length()) {
+ getHolder().createWarningAnnotation(node, RestBundle.message("ANN.title.length"));
+ }
+ }
+}
diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml
index 6c02c7a..cf37b69 100644
--- a/python/src/META-INF/python-core.xml
+++ b/python/src/META-INF/python-core.xml
@@ -369,6 +369,8 @@
<completion.contributor language="Python"
implementationClass="com.jetbrains.python.codeInsight.completion.PyClassNameCompletionContributor"/>
+ <completion.contributor language="Python"
+ implementationClass="com.jetbrains.python.codeInsight.completion.PyBracketProtectingCompletionContributor"/>
<weigher key="completion" implementationClass="com.jetbrains.python.codeInsight.completion.PythonCompletionWeigher" order="first"/>
<completion.confidence language="Python" implementationClass="com.jetbrains.python.codeInsight.completion.PyCompletionConfidence"/>
<typedHandler implementation="com.jetbrains.python.console.completion.PythonConsoleAutopopupBlockingHandler" id="pydevBlockAutoPopup"
@@ -511,6 +513,7 @@
<extensionPoints>
<extensionPoint qualifiedName="Pythonid.importResolver" interface="com.jetbrains.python.psi.impl.PyImportResolver"/>
+ <extensionPoint qualifiedName="Pythonid.resolveResultRater" interface="com.jetbrains.python.psi.impl.PyResolveResultRater"/>
<extensionPoint qualifiedName="Pythonid.typeProvider" interface="com.jetbrains.python.psi.impl.PyTypeProvider"/>
<extensionPoint qualifiedName="Pythonid.pySuperMethodsSearch" interface="com.intellij.util.QueryExecutor"/>
<extensionPoint qualifiedName="Pythonid.pyClassInheritorsSearch" interface="com.intellij.util.QueryExecutor"/>
@@ -544,7 +547,6 @@
<pySuperMethodsSearch implementation="com.jetbrains.python.psi.search.PySuperMethodsSearchExecutor"/>
<pyClassInheritorsSearch implementation="com.jetbrains.python.psi.search.PyClassInheritorsSearchExecutor"/>
<pyOverridingMethodsSearch implementation="com.jetbrains.python.psi.search.PyOverridingMethodsSearchExecutor"/>
- <runnableScriptFilter implementation="com.jetbrains.python.testing.pytest.PyTestRunnableScriptFilter"/>
<runnableScriptFilter implementation="com.jetbrains.python.testing.PythonUnitTestRunnableScriptFilter"/>
<dumbAnnotator implementation="com.jetbrains.python.validation.DocStringAnnotator"/>
<dumbAnnotator implementation="com.jetbrains.python.validation.PyDefinitionsAnnotator"/>
diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties
index 5ee3ef7..28289e0 100644
--- a/python/src/com/jetbrains/python/PyBundle.properties
+++ b/python/src/com/jetbrains/python/PyBundle.properties
@@ -637,6 +637,7 @@
PARSE.expected.colon=':' expected
PARSE.expected.rpar=')' expected
PARSE.expected.lpar='(' expected
+PARSE.expected.rbrace='}' expected
PARSE.expected.tick='`' (backtick) expected
PARSE.expected.name=name expected
PARSE.expected.colon.or.rbracket=':' or ']' expected
diff --git a/python/src/com/jetbrains/python/codeInsight/PyInjectionUtil.java b/python/src/com/jetbrains/python/codeInsight/PyInjectionUtil.java
index d68e6c6..9a7edad 100644
--- a/python/src/com/jetbrains/python/codeInsight/PyInjectionUtil.java
+++ b/python/src/com/jetbrains/python/codeInsight/PyInjectionUtil.java
@@ -23,6 +23,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Arrays;
import java.util.List;
import static com.jetbrains.python.inspections.PyStringFormatParser.*;
@@ -31,15 +32,22 @@
* @author vlan
*/
public class PyInjectionUtil {
+ public static final List<Class<? extends PyExpression>> ELEMENTS_TO_INJECT_IN =
+ Arrays.asList(PyStringLiteralExpression.class, PyParenthesizedExpression.class, PyBinaryExpression.class, PyCallExpression.class);
+
private PyInjectionUtil() {}
/**
- * Returns true if the element is the largest expression that represents a string literal, possibly with concatenation, parentheses,
- * or formatting.
+ * Returns the largest expression in the specified context that represents a string literal suitable for language injection, possibly
+ * with concatenation, parentheses, or formatting.
*/
- public static boolean isLargestStringLiteral(@NotNull PsiElement element) {
- final PsiElement parent = element.getParent();
- return isStringLiteralPart(element) && (parent == null || !isStringLiteralPart(parent));
+ @Nullable
+ public static PsiElement getLargestStringLiteral(@NotNull PsiElement context) {
+ PsiElement element = null;
+ for (PsiElement current = context; current != null && isStringLiteralPart(current, element); current = current.getParent()) {
+ element = current;
+ }
+ return element;
}
/**
@@ -47,27 +55,35 @@
* string concatenations or formatting.
*/
public static void registerStringLiteralInjection(@NotNull PsiElement element, @NotNull MultiHostRegistrar registrar) {
- processStringLiteral(element, registrar, "", "", Formatting.NONE);
+ processStringLiteral(element, registrar, "", "", Formatting.PERCENT);
}
- private static boolean isStringLiteralPart(@NotNull PsiElement element) {
- if (element instanceof PyStringLiteralExpression) {
+ private static boolean isStringLiteralPart(@NotNull PsiElement element, @Nullable PsiElement context) {
+ if (element == context) {
+ return true;
+ }
+ else if (element instanceof PyStringLiteralExpression) {
return true;
}
else if (element instanceof PyParenthesizedExpression) {
final PyExpression contained = ((PyParenthesizedExpression)element).getContainedExpression();
- return contained != null && isStringLiteralPart(contained);
+ return contained != null && isStringLiteralPart(contained, context);
}
else if (element instanceof PyBinaryExpression) {
final PyBinaryExpression expr = (PyBinaryExpression)element;
final PyExpression left = expr.getLeftExpression();
final PyExpression right = expr.getRightExpression();
- return (expr.isOperator("+") && (isStringLiteralPart(left) || right != null && isStringLiteralPart(right))) ||
- expr.isOperator("%") && isStringLiteralPart(left);
+ if (expr.isOperator("+")) {
+ return isStringLiteralPart(left, context) || right != null && isStringLiteralPart(right, context);
+ }
+ else if (expr.isOperator("%")) {
+ return right != context && isStringLiteralPart(left, context);
+ }
+ return false;
}
else if (element instanceof PyCallExpression) {
final PyExpression qualifier = getFormatCallQualifier((PyCallExpression)element);
- return qualifier != null && isStringLiteralPart(qualifier);
+ return qualifier != null && isStringLiteralPart(qualifier, context);
}
return false;
}
@@ -100,9 +116,25 @@
final FormatStringChunk chunk = chunks.get(i);
if (chunk instanceof ConstantChunk) {
final int nextIndex = i + 1;
- final String chunkPrefix = i == 1 && chunks.get(0) instanceof SubstitutionChunk ? missingValue : "";
- final String chunkSuffix = nextIndex < chunks.size() &&
- chunks.get(nextIndex) instanceof SubstitutionChunk ? missingValue : "";
+ final String chunkPrefix;
+ if (i == 1 && chunks.get(0) instanceof SubstitutionChunk) {
+ chunkPrefix = missingValue;
+ }
+ else if (i == 0) {
+ chunkPrefix = prefix;
+ } else {
+ chunkPrefix = "";
+ }
+ final String chunkSuffix;
+ if (nextIndex < chunks.size() && chunks.get(nextIndex) instanceof SubstitutionChunk) {
+ chunkSuffix = missingValue;
+ }
+ else if (nextIndex == chunks.size()) {
+ chunkSuffix = suffix;
+ }
+ else {
+ chunkSuffix = "";
+ }
final TextRange chunkRange = chunk.getTextRange().shiftRight(range.getStartOffset());
registrar.addPlace(chunkPrefix, chunkSuffix, expr, chunkRange);
}
@@ -123,9 +155,9 @@
final PyBinaryExpression expr = (PyBinaryExpression)element;
final PyExpression left = expr.getLeftExpression();
final PyExpression right = expr.getRightExpression();
- final boolean isLeftString = isStringLiteralPart(left);
+ final boolean isLeftString = isStringLiteralPart(left, null);
if (expr.isOperator("+")) {
- final boolean isRightString = right != null && isStringLiteralPart(right);
+ final boolean isRightString = right != null && isStringLiteralPart(right, null);
if (isLeftString) {
processStringLiteral(left, registrar, prefix, isRightString ? "" : missingValue, formatting);
}
diff --git a/python/src/com/jetbrains/python/codeInsight/PyInjectorBase.java b/python/src/com/jetbrains/python/codeInsight/PyInjectorBase.java
new file mode 100644
index 0000000..98ae8c4
--- /dev/null
+++ b/python/src/com/jetbrains/python/codeInsight/PyInjectorBase.java
@@ -0,0 +1,43 @@
+package com.jetbrains.python.codeInsight;
+
+import com.intellij.lang.Language;
+import com.intellij.lang.injection.MultiHostInjector;
+import com.intellij.lang.injection.MultiHostRegistrar;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author vlan
+ */
+public abstract class PyInjectorBase implements MultiHostInjector {
+ @Override
+ public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
+ registerInjection(registrar, context);
+ }
+
+ @NotNull
+ @Override
+ public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
+ return PyInjectionUtil.ELEMENTS_TO_INJECT_IN;
+ }
+
+ @Nullable
+ public abstract Language getInjectedLanguage(@NotNull PsiElement context);
+
+ protected boolean registerInjection(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
+ final Language language = getInjectedLanguage(context);
+ if (language != null) {
+ final PsiElement element = PyInjectionUtil.getLargestStringLiteral(context);
+ if (element != null) {
+ registrar.startInjecting(language);
+ PyInjectionUtil.registerStringLiteralInjection(element, registrar);
+ registrar.doneInjecting();
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyBracketProtectingCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyBracketProtectingCompletionContributor.java
new file mode 100644
index 0000000..766e5be
--- /dev/null
+++ b/python/src/com/jetbrains/python/codeInsight/completion/PyBracketProtectingCompletionContributor.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.codeInsight.completion;
+
+import com.intellij.codeInsight.completion.CompletionContributor;
+import com.intellij.codeInsight.completion.CompletionInitializationContext;
+import com.intellij.psi.PsiReference;
+import com.jetbrains.python.psi.impl.references.PyOperatorReference;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class PyBracketProtectingCompletionContributor extends CompletionContributor {
+ @Override
+ public void beforeCompletion(@NotNull CompletionInitializationContext context) {
+ PsiReference ref = context.getFile().findReferenceAt(context.getSelectionEndOffset());
+ if (ref instanceof PyOperatorReference) {
+ context.setReplacementOffset(context.getIdentifierEndOffset());
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyDocstringCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyDocstringCompletionContributor.java
index 84d4b88..272adfa 100644
--- a/python/src/com/jetbrains/python/codeInsight/completion/PyDocstringCompletionContributor.java
+++ b/python/src/com/jetbrains/python/codeInsight/completion/PyDocstringCompletionContributor.java
@@ -16,6 +16,7 @@
package com.jetbrains.python.codeInsight.completion;
import com.intellij.codeInsight.completion.*;
+import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
@@ -23,8 +24,6 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ProcessingContext;
-import com.jetbrains.python.PyTokenTypes;
-import com.jetbrains.python.documentation.PyDocumentationSettings;
import com.jetbrains.python.psi.PyDocStringOwner;
import com.jetbrains.python.psi.PyStringLiteralExpression;
import com.jetbrains.python.refactoring.PyRefactoringUtil;
@@ -32,7 +31,9 @@
import java.util.Collection;
+import static com.intellij.patterns.PlatformPatterns.psiComment;
import static com.intellij.patterns.PlatformPatterns.psiElement;
+import static com.intellij.patterns.StandardPatterns.or;
/**
* User : ktisha
@@ -40,7 +41,7 @@
public class PyDocstringCompletionContributor extends CompletionContributor {
public PyDocstringCompletionContributor() {
extend(CompletionType.BASIC,
- psiElement().inside(PyStringLiteralExpression.class).withElementType(PyTokenTypes.DOCSTRING),
+ or(psiElement().inside(PyStringLiteralExpression.class), psiComment()),
new IdentifierCompletionProvider());
}
@@ -54,23 +55,22 @@
ProcessingContext context,
@NotNull CompletionResultSet result) {
if (parameters.isAutoPopup()) return;
- final PyDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(parameters.getOriginalPosition(), PyDocStringOwner.class);
- if (docStringOwner != null) {
- final PsiFile file = docStringOwner.getContainingFile();
- final Module module = ModuleUtilCore.findModuleForPsiElement(docStringOwner);
- if (module != null) {
- final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(module);
- if (!settings.isPlain(file)) return;
- result = result.withPrefixMatcher(getPrefix(parameters.getOffset(), file));
- final Collection<String> identifiers = PyRefactoringUtil.collectUsedNames(docStringOwner);
- for (String identifier : identifiers)
- result.addElement(LookupElementBuilder.create(identifier));
+ final PsiElement element = parameters.getOriginalPosition();
+ if (element == null) return;
+ final PsiFile file = element.getContainingFile();
+ if (file.findReferenceAt(parameters.getOffset()) != null) return;
+ final PyDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(element, PyDocStringOwner.class);
+ final Module module = ModuleUtilCore.findModuleForPsiElement(element);
+ if (module != null) {
+ result = result.withPrefixMatcher(getPrefix(parameters.getOffset(), file));
+ final Collection<String> identifiers = PyRefactoringUtil.collectUsedNames(docStringOwner);
+ for (String identifier : identifiers)
+ result.addElement(LookupElementBuilder.create(identifier).withAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE));
- final Collection<String> fileIdentifiers = PyRefactoringUtil.collectUsedNames(parameters.getOriginalFile());
- for (String identifier : fileIdentifiers)
- result.addElement(LookupElementBuilder.create(identifier));
- }
+ final Collection<String> fileIdentifiers = PyRefactoringUtil.collectUsedNames(parameters.getOriginalFile());
+ for (String identifier : fileIdentifiers)
+ result.addElement(LookupElementBuilder.create(identifier).withAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE));
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/regexp/PythonRegexpInjector.java b/python/src/com/jetbrains/python/codeInsight/regexp/PythonRegexpInjector.java
index 39c9aff..bb23c47 100644
--- a/python/src/com/jetbrains/python/codeInsight/regexp/PythonRegexpInjector.java
+++ b/python/src/com/jetbrains/python/codeInsight/regexp/PythonRegexpInjector.java
@@ -67,7 +67,7 @@
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
final PsiElement contextParent = context.getParent();
- if (PyInjectionUtil.isLargestStringLiteral(context) && contextParent instanceof PyArgumentList) {
+ if (PyInjectionUtil.getLargestStringLiteral(context) == context && contextParent instanceof PyArgumentList) {
final PyExpression[] args = ((PyArgumentList)contextParent).getArguments();
int index = ArrayUtil.indexOf(args, context);
PyCallExpression call = PsiTreeUtil.getParentOfType(context, PyCallExpression.class);
diff --git a/python/src/com/jetbrains/python/console/PyConsoleOptions.java b/python/src/com/jetbrains/python/console/PyConsoleOptions.java
index 6816b93..d02b670 100644
--- a/python/src/com/jetbrains/python/console/PyConsoleOptions.java
+++ b/python/src/com/jetbrains/python/console/PyConsoleOptions.java
@@ -19,8 +19,12 @@
import com.intellij.openapi.components.*;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
+import com.intellij.util.PathMappingSettings;
import com.intellij.util.containers.ComparatorUtil;
+import com.intellij.util.xmlb.annotations.*;
import com.jetbrains.python.run.AbstractPyCommonOptionsForm;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Map;
@@ -80,6 +84,7 @@
public boolean myShowSeparatorLine = true;
}
+ @Tag("console-settings")
public static class PyConsoleSettings {
public String myCustomStartScript = "";
public String mySdkHome = null;
@@ -90,14 +95,8 @@
public String myWorkingDirectory = "";
public boolean myAddContentRoots = true;
public boolean myAddSourceRoots;
-
- public String getCustomStartScript() {
- return myCustomStartScript;
- }
-
- public String getSdkHome() {
- return mySdkHome;
- }
+ @NotNull
+ private PathMappingSettings myMappings = new PathMappingSettings();
public void apply(AbstractPyCommonOptionsForm form) {
mySdkHome = form.getSdkHome();
@@ -109,6 +108,7 @@
myAddContentRoots = form.addContentRoots();
myAddSourceRoots = form.addSourceRoots();
+ myMappings = form.getMappingSettings() == null ? new PathMappingSettings() : form.getMappingSettings();
}
public boolean isModified(AbstractPyCommonOptionsForm form) {
@@ -119,7 +119,8 @@
myAddContentRoots != form.addContentRoots() ||
myAddSourceRoots != form.addSourceRoots()
|| !ComparatorUtil.equalsNullable(myModuleName, form.getModule() == null ? null : form.getModule().getName())
- || !myWorkingDirectory.equals(form.getWorkingDirectory());
+ || !myWorkingDirectory.equals(form.getWorkingDirectory())
+ || !myMappings.equals(form.getMappingSettings());
}
public void reset(Project project, AbstractPyCommonOptionsForm form) {
@@ -143,33 +144,103 @@
myModuleName = form.getModule().getName();
}
- form.setWorkingDirectory(form.getWorkingDirectory());
+ form.setWorkingDirectory(myWorkingDirectory);
+
+ form.setMappingSettings(myMappings);
}
+ @Attribute("custom-start-script")
+ public String getCustomStartScript() {
+ return myCustomStartScript;
+ }
+
+ @Attribute("sdk-home")
+ public String getSdkHome() {
+ return mySdkHome;
+ }
+
+ @Attribute("module-name")
public String getModuleName() {
return myModuleName;
}
+ @Attribute("working-directory")
public String getWorkingDirectory() {
return myWorkingDirectory;
}
+ @Attribute("is-module-sdk")
public boolean isUseModuleSdk() {
return myUseModuleSdk;
}
+ @Tag("envs")
+ @Property(surroundWithTag = false)
+ @MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, keyAttributeName = "key",
+ entryTagName = "env", valueAttributeName = "value", surroundValueWithTag = false)
public Map<String, String> getEnvs() {
return myEnvs;
}
+ @Attribute("add-content-roots")
public boolean addContentRoots() {
return myAddContentRoots;
}
+ @Attribute("add-source-roots")
public boolean addSourceRoots() {
return myAddSourceRoots;
}
+ @Attribute("interpreter-options")
+ public String getInterpreterOptions() {
+ return myInterpreterOptions;
+ }
+
+ @AbstractCollection(surroundWithTag = false)
+ public PathMappingSettings getMappings() {
+ return myMappings;
+ }
+
+ public void setCustomStartScript(String customStartScript) {
+ myCustomStartScript = customStartScript;
+ }
+
+ public void setSdkHome(String sdkHome) {
+ mySdkHome = sdkHome;
+ }
+
+ public void setInterpreterOptions(String interpreterOptions) {
+ myInterpreterOptions = interpreterOptions;
+ }
+
+ public void setUseModuleSdk(boolean useModuleSdk) {
+ myUseModuleSdk = useModuleSdk;
+ }
+
+ public void setModuleName(String moduleName) {
+ myModuleName = moduleName;
+ }
+
+ public void setEnvs(Map<String, String> envs) {
+ myEnvs = envs;
+ }
+
+ public void setWorkingDirectory(String workingDirectory) {
+ myWorkingDirectory = workingDirectory;
+ }
+
+ public void setAddContentRoots(boolean addContentRoots) {
+ myAddContentRoots = addContentRoots;
+ }
+
+ public void setAddSourceRoots(boolean addSourceRoots) {
+ myAddSourceRoots = addSourceRoots;
+ }
+
+ public void setMappings(@Nullable PathMappingSettings mappings) {
+ myMappings = mappings != null ? mappings : new PathMappingSettings();
+ }
}
}
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java
index b0ef1d3..6af6c13 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleCommunication.java
@@ -53,10 +53,11 @@
*
* @author Fabio
*/
-public class PydevConsoleCommunication extends AbstractConsoleCommunication implements IScriptConsoleCommunication, XmlRpcHandler,
+public class PydevConsoleCommunication extends AbstractConsoleCommunication implements XmlRpcHandler,
PyFrameAccessor {
private static final String EXEC_LINE = "execLine";
+ private static final String EXEC_MULTILINE = "execMultipleLines";
private static final String GET_COMPLETIONS = "getCompletions";
private static final String GET_DESCRIPTION = "getDescription";
private static final String GET_FRAME = "getFrame";
@@ -64,6 +65,7 @@
private static final String CHANGE_VARIABLE = "changeVariable";
private static final String HANDSHAKE = "handshake";
private static final String CLOSE = "close";
+
/**
* XML-RPC client for sending messages to the server.
*/
@@ -167,7 +169,7 @@
*/
public Object execute(String method, Vector params) throws Exception {
if ("NotifyFinished".equals(method)) {
- return execNotifyFinished();
+ return execNotifyFinished((Boolean)params.get(0));
}
else if ("RequestInput".equals(method)) {
return execRequestInput();
@@ -223,9 +225,9 @@
return Boolean.FALSE;
}
- private Object execNotifyFinished() {
+ private Object execNotifyFinished(boolean more) {
setExecuting(false);
- notifyCommandExecuted();
+ notifyCommandExecuted(more);
return true;
}
@@ -261,12 +263,13 @@
/**
* Executes the needed command
*
+ * @param command
* @return a Pair with (null, more) or (error, false)
* @throws XmlRpcException
*/
- protected Pair<String, Boolean> exec(final String command) throws XmlRpcException {
+ protected Pair<String, Boolean> exec(final ConsoleCodeFragment command) throws XmlRpcException {
setExecuting(true);
- Object execute = myClient.execute(EXEC_LINE, new Object[]{command});
+ Object execute = myClient.execute(command.isSingleLine() ? EXEC_LINE : EXEC_MULTILINE, new Object[]{command.getText()});
Object object;
if (execute instanceof Vector) {
@@ -278,6 +281,15 @@
else {
object = execute;
}
+ Pair<String, Boolean> result = parseResult(object);
+ if (result.second) {
+ setExecuting(false);
+ }
+
+ return result;
+ }
+
+ private Pair<String, Boolean> parseResult(Object object) {
if (object instanceof Boolean) {
return new Pair<String, Boolean>(null, (Boolean)object);
}
@@ -314,10 +326,10 @@
*
* @param command the command to be executed in the client
*/
- public void execInterpreter(final String command, final Function<InterpreterResponse, Object> onResponseReceived) {
+ public void execInterpreter(final ConsoleCodeFragment command, final Function<InterpreterResponse, Object> onResponseReceived) {
nextResponse = null;
if (waitingForInput) {
- inputReceived = command;
+ inputReceived = command.getText();
waitingForInput = false;
//the thread that we started in the last exec is still alive if we were waiting for an input.
}
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
index 20e8655..3dd6187 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
@@ -32,6 +32,7 @@
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.impl.source.codeStyle.IndentHelperImpl;
import com.intellij.util.Function;
+import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.console.pydev.ConsoleCommunication;
@@ -40,13 +41,10 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Scanner;
-
/**
* @author traff
*/
public class PydevConsoleExecuteActionHandler extends ConsoleExecuteActionHandler implements ConsoleCommunicationListener {
-
private final LanguageConsoleView myConsoleView;
private String myInMultilineStringState = null;
@@ -67,19 +65,20 @@
@Override
public void processLine(final String text) {
- processLine(text, true);
+ processLine(text, false);
}
- public void processLine(final String text, boolean execAnyway) {
+ public void processLine(@NotNull final String text, boolean execAnyway) {
int indentBefore = myCurrentIndentSize;
if (text.isEmpty()) {
processOneLine(text);
}
else {
- Scanner s = new Scanner(text);
- while (s.hasNextLine()) {
- String line = s.nextLine();
- processOneLine(line);
+ if (StringUtil.countNewLines(text.trim()) > 0) {
+ executeMultiLine(text);
+ }
+ else {
+ processOneLine(text);
}
}
if (execAnyway && myCurrentIndentSize > 0 && indentBefore == 0) { //if code was indented and we need to exec anyway
@@ -87,6 +86,19 @@
}
}
+ private void executeMultiLine(@NotNull String text) {
+ if (myInputBuffer == null) {
+ myInputBuffer = new StringBuilder();
+ }
+
+ myInputBuffer.append(text);
+
+ final LanguageConsoleImpl console = myConsoleView.getConsole();
+ final Editor currentEditor = console.getConsoleEditor();
+
+ sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), false), console, currentEditor);
+ }
+
private void processOneLine(String line) {
int indentSize = IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false);
line = StringUtil.trimTrailing(line);
@@ -169,21 +181,27 @@
indentEditor(currentEditor, indent);
more(console, currentEditor);
+ myConsoleCommunication.notifyCommandExecuted(true);
return;
}
}
+ sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), true), console, currentEditor);
+ }
+
+ private void sendLineToConsole(@NotNull final ConsoleCommunication.ConsoleCodeFragment code,
+ @NotNull final LanguageConsoleImpl console,
+ @NotNull final Editor currentEditor) {
if (myConsoleCommunication != null) {
final boolean waitedForInputBefore = myConsoleCommunication.isWaitingForInput();
- final String command = myInputBuffer.toString();
if (myConsoleCommunication.isWaitingForInput()) {
myInputBuffer.setLength(0);
}
else {
executingPrompt(console);
}
- myConsoleCommunication.execInterpreter(command, new Function<InterpreterResponse, Object>() {
+ myConsoleCommunication.execInterpreter(code, new Function<InterpreterResponse, Object>() {
public Object fun(final InterpreterResponse interpreterResponse) {
// clear
myInputBuffer = null;
@@ -192,9 +210,15 @@
more(console, currentEditor);
if (myCurrentIndentSize == 0) {
// compute current indentation
- setCurrentIndentSize(IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false) + getPythonIndent());
+ setCurrentIndentSize(
+ IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, lastLine(code.getText()), false) + getPythonIndent());
// In this case we can insert indent automatically
- indentEditor(currentEditor, myCurrentIndentSize);
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ indentEditor(currentEditor, myCurrentIndentSize);
+ }
+ });
}
}
else {
@@ -215,6 +239,11 @@
}
}
+ private static String lastLine(@NotNull String text) {
+ String[] lines = StringUtil.splitByLinesDontTrim(text);
+ return lines[lines.length - 1];
+ }
+
private void ordinaryPrompt(LanguageConsoleImpl console, Editor currentEditor) {
if (!myConsoleCommunication.isExecuting()) {
if (!PyConsoleUtil.ORDINARY_PROMPT.equals(console.getPrompt())) {
@@ -243,10 +272,13 @@
}
@Override
- public void commandExecuted() {
- final LanguageConsoleImpl console = myConsoleView.getConsole();
- final Editor currentEditor = console.getConsoleEditor();
- ordinaryPrompt(console, currentEditor);
+ public void commandExecuted(boolean more) {
+ if (!more) {
+ final LanguageConsoleImpl console = myConsoleView.getConsole();
+ final Editor currentEditor = console.getConsoleEditor();
+
+ ordinaryPrompt(console, currentEditor);
+ }
}
@Override
@@ -335,7 +367,7 @@
}
@Override
- public void runExecuteAction(LanguageConsoleImpl languageConsole) {
+ public void runExecuteAction(@NotNull LanguageConsoleImpl languageConsole) {
if (isEnabled()) {
if (!canExecuteNow()) {
HintManager.getInstance().showErrorHint(languageConsole.getConsoleEditor(), getPrevCommandRunningMessage());
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java
index ddf62ed..27d964a 100644
--- a/python/src/com/jetbrains/python/console/PythonConsoleView.java
+++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java
@@ -152,7 +152,9 @@
private void doExecute(String code) {
- executeInConsole(PyConsoleIndentUtil.normalize(code, myExecuteActionHandler.getCurrentIndentSize()));
+ String codeFragment = PyConsoleIndentUtil.normalize(code, myExecuteActionHandler.getCurrentIndentSize());
+ codeFragment += "\n";
+ executeInConsole(codeFragment);
}
public void executeInConsole(final String code) {
@@ -383,7 +385,7 @@
final XStandaloneVariablesView view = new XStandaloneVariablesView(myProject, new PyDebuggerEditorsProvider(), stackFrame);
consoleCommunication.addCommunicationListener(new ConsoleCommunicationListener() {
@Override
- public void commandExecuted() {
+ public void commandExecuted(boolean more) {
view.rebuildView();
}
diff --git a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java
index 8f55aed..d24a2a8a 100644
--- a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java
+++ b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java
@@ -63,8 +63,8 @@
return false;
}
- protected void exec(final String command, final ProcessDebugger.DebugCallback<Pair<String, Boolean>> callback) {
- myDebugProcess.consoleExec(command, new ProcessDebugger.DebugCallback<String>() {
+ protected void exec(final ConsoleCodeFragment command, final ProcessDebugger.DebugCallback<Pair<String, Boolean>> callback) {
+ myDebugProcess.consoleExec(command.getText(), new ProcessDebugger.DebugCallback<String>() {
@Override
public void ok(String value) {
callback.ok(parseExecResponseString(value));
@@ -77,9 +77,9 @@
});
}
- public void execInterpreter(String s, final Function<InterpreterResponse, Object> callback) {
- myExpression.append(s);
- exec(myExpression.toString(), new ProcessDebugger.DebugCallback<Pair<String, Boolean>>() {
+ public void execInterpreter(ConsoleCodeFragment code, final Function<InterpreterResponse, Object> callback) {
+ myExpression.append(code.getText());
+ exec(new ConsoleCodeFragment(myExpression.toString(), false), new ProcessDebugger.DebugCallback<Pair<String, Boolean>>() {
@Override
public void ok(Pair<String, Boolean> executed) {
boolean more = executed.second;
diff --git a/python/src/com/jetbrains/python/inspections/PyMethodMayBeStaticInspection.java b/python/src/com/jetbrains/python/inspections/PyMethodMayBeStaticInspection.java
index 2bc6424..71f2772 100644
--- a/python/src/com/jetbrains/python/inspections/PyMethodMayBeStaticInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyMethodMayBeStaticInspection.java
@@ -70,7 +70,9 @@
if (!supers.isEmpty()) return;
final Collection<PyFunction> overrides = PyOverridingMethodsSearch.search(node, true).findAll();
if (!overrides.isEmpty()) return;
- if (PyUtil.isDecoratedAsAbstract(node) || node.getModifier() != null) return;
+ final PyDecoratorList decoratorList = node.getDecoratorList();
+ if (decoratorList != null) return;
+ if (node.getModifier() != null) return;
final Property property = containingClass.findPropertyByCallable(node);
if (property != null) return;
diff --git a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java
index 65c791a..790b155 100644
--- a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java
+++ b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java
@@ -236,7 +236,7 @@
break;
}
}
- myBuilder.advanceLexer();
+ checkMatches(PyTokenTypes.RBRACE, message("PARSE.expected.rbrace"));
startMarker.done(PyElementTypes.DICT_LITERAL_EXPRESSION);
}
}
@@ -264,7 +264,7 @@
break;
}
}
- myBuilder.advanceLexer();
+ checkMatches(PyTokenTypes.RBRACE, message("PARSE.expected.rbrace"));
startMarker.done(PyElementTypes.SET_LITERAL_EXPRESSION);
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyStringLiteralExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyStringLiteralExpressionImpl.java
index 7f03dcd..7595fde 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyStringLiteralExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyStringLiteralExpressionImpl.java
@@ -21,7 +21,6 @@
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
@@ -50,9 +49,21 @@
public static final Pattern PATTERN_ESCAPE = Pattern
.compile("\\\\(\n|\\\\|'|\"|a|b|f|n|r|t|v|([0-7]{1,3})|x([0-9a-fA-F]{1,2})" + "|N(\\{.*?\\})|u([0-9a-fA-F]{4})|U([0-9a-fA-F]{8}))");
// -> 1 -> 2 <--> 3 <- -> 4 <--> 5 <- -> 6 <-<-
+
+ private enum EscapeRegexGroup {
+ WHOLE_MATCH,
+ ESCAPED_SUBSTRING,
+ OCTAL,
+ HEXADECIMAL,
+ UNICODE_NAMED,
+ UNICODE_16BIT,
+ UNICODE_32BIT
+ }
+
private static final Map<String, String> escapeMap = initializeEscapeMap();
private String stringValue;
private List<TextRange> valueTextRanges;
+ @Nullable private List<Pair<TextRange, String>> myDecodedFragments;
private final DefaultRegExpPropertiesProvider myPropertiesProvider;
private static Map<String, String> initializeEscapeMap() {
@@ -85,6 +96,7 @@
super.subtreeChanged();
stringValue = null;
valueTextRanges = null;
+ myDecodedFragments = null;
}
public List<TextRange> getStringValueTextRanges() {
@@ -143,20 +155,82 @@
return text.length() > 0 && Character.toUpperCase(text.charAt(0)) == 'C';
}
- public void iterateCharacterRanges(TextRangeConsumer consumer) {
- int elStart = getTextRange().getStartOffset();
- for (ASTNode child : getStringNodes()) {
- final String text = child.getText();
- TextRange textRange = getNodeTextRange(text);
- int offset = child.getTextRange().getStartOffset() - elStart + textRange.getStartOffset();
- String undecoded = textRange.substring(text);
- if (!iterateCharacterRanges(consumer, undecoded, offset, isRaw(text), isUnicode(text))) {
- break;
+ @Override
+ @NotNull
+ public List<Pair<TextRange, String>> getDecodedFragments() {
+ if (myDecodedFragments == null) {
+ final List<Pair<TextRange, String>> result = new ArrayList<Pair<TextRange, String>>();
+ final int elementStart = getTextRange().getStartOffset();
+ for (ASTNode node : getStringNodes()) {
+ final String text = node.getText();
+ final TextRange textRange = getNodeTextRange(text);
+ final int offset = node.getTextRange().getStartOffset() - elementStart + textRange.getStartOffset();
+ final String encoded = textRange.substring(text);
+ result.addAll(getDecodedFragments(encoded, offset, isRaw(text), isUnicode(text)));
}
+ myDecodedFragments = result;
}
+ return myDecodedFragments;
}
+ @NotNull
+ private static List<Pair<TextRange, String>> getDecodedFragments(@NotNull String encoded, int offset, boolean raw, boolean unicode) {
+ final List<Pair<TextRange, String>> result = new ArrayList<Pair<TextRange, String>>();
+ final Matcher escMatcher = PATTERN_ESCAPE.matcher(encoded);
+ int index = 0;
+ while (escMatcher.find(index)) {
+ if (index < escMatcher.start()) {
+ final TextRange range = TextRange.create(index, escMatcher.start());
+ final TextRange offsetRange = range.shiftRight(offset);
+ result.add(Pair.create(offsetRange, range.substring(encoded)));
+ }
+ final String octal = escapeRegexGroup(escMatcher, EscapeRegexGroup.OCTAL);
+ final String hex = escapeRegexGroup(escMatcher, EscapeRegexGroup.HEXADECIMAL);
+ // TODO: Implement unicode character name escapes: EscapeRegexGroup.UNICODE_NAMED
+ final String unicode16 = escapeRegexGroup(escMatcher, EscapeRegexGroup.UNICODE_16BIT);
+ final String unicode32 = escapeRegexGroup(escMatcher, EscapeRegexGroup.UNICODE_32BIT);
+
+ final boolean escapedUnicode = raw && unicode || !raw;
+
+ final String str;
+ if (!raw && octal != null) {
+ str = new String(new char[]{(char)Integer.parseInt(octal, 8)});
+ }
+ else if (!raw && hex != null) {
+ str = new String(new char[]{(char)Integer.parseInt(hex, 16)});
+ }
+ else if (escapedUnicode && unicode16 != null) {
+ str = unicode ? new String(new char[]{(char)Integer.parseInt(unicode16, 16)}) : unicode16;
+ }
+ else if (escapedUnicode && unicode32 != null) {
+ str = unicode ? new String(Character.toChars((int)Long.parseLong(unicode32, 16))) : unicode32;
+ }
+ else if (raw) {
+ str = escapeRegexGroup(escMatcher, EscapeRegexGroup.WHOLE_MATCH);
+ }
+ else {
+ final String toReplace = escapeRegexGroup(escMatcher, EscapeRegexGroup.ESCAPED_SUBSTRING);
+ str = escapeMap.get(toReplace);
+ }
+
+ if (str != null) {
+ final TextRange wholeMatch = TextRange.create(escMatcher.start(), escMatcher.end());
+ result.add(Pair.create(wholeMatch.shiftRight(offset), str));
+ }
+
+ index = escMatcher.end();
+ }
+ final TextRange range = TextRange.create(index, encoded.length());
+ final TextRange offRange = range.shiftRight(offset);
+ result.add(Pair.create(offRange, range.substring(encoded)));
+ return result;
+ }
+
+ @Nullable
+ private static String escapeRegexGroup(@NotNull Matcher matcher, EscapeRegexGroup group) {
+ return matcher.group(group.ordinal());
+ }
public List<ASTNode> getStringNodes() {
return Arrays.asList(getNode().getChildren(PyTokenTypes.STRING_NODES));
@@ -165,14 +239,11 @@
public String getStringValue() {
//ASTNode child = getNode().getFirstChildNode();
//assert child != null;
- if (stringValue == null) {
+ if (stringValue == null) {
final StringBuilder out = new StringBuilder();
- iterateCharacterRanges(new TextRangeConsumer() {
- public boolean process(int startOffset, int endOffset, String value) {
- out.append(value);
- return true;
- }
- });
+ for (Pair<TextRange, String> fragment : getDecodedFragments()) {
+ out.append(fragment.getSecond());
+ }
stringValue = out.toString();
}
return stringValue;
@@ -190,106 +261,6 @@
return new TextRange(0, getTextLength());
}
- private static boolean iterateCharacterRanges(TextRangeConsumer consumer, String undecoded, int off, boolean raw, boolean unicode) {
- if (raw) {
- return iterateRawCharacterRanges(consumer, undecoded, off, unicode);
- }
- Matcher escMatcher = PATTERN_ESCAPE.matcher(undecoded);
- int index = 0;
- while (escMatcher.find(index)) {
- for (int i = index; i < escMatcher.start(); i++) {
- if (!consumer.process(off + i, off + i + 1, Character.toString(undecoded.charAt(i)))) {
- return false;
- }
- }
- String octal = escMatcher.group(2);
- String hex = escMatcher.group(3);
- String str = null;
- if (octal != null) {
- str = new String(new char[]{(char)Integer.parseInt(octal, 8)});
-
- }
- else if (hex != null) {
- str = new String(new char[]{(char)Integer.parseInt(hex, 16)});
-
- }
- else {
- String toReplace = escMatcher.group(1);
- String replacement = escapeMap.get(toReplace);
- if (replacement != null) {
- str = replacement;
- }
- }
- String unicodeName = escMatcher.group(4);
- String unicode32 = escMatcher.group(6);
-
- if (unicode32 != null) {
- str = unicode ? new String(Character.toChars((int)Long.parseLong(unicode32, 16))) : unicode32;
- }
- if (unicodeName != null) {
- //TOLATER: implement unicode character name escapes
- }
- String unicode16 = escMatcher.group(5);
- if (unicode16 != null) {
- str = unicode ? new String(new char[]{(char)Integer.parseInt(unicode16, 16)}) : unicode16;
- }
-
- if (str != null) {
- int start = escMatcher.start();
- int end = escMatcher.end();
- if (!consumer.process(off + start, off + end, str)) {
- return false;
- }
- }
- index = escMatcher.end();
- }
- for (int i = index; i < undecoded.length(); i++) {
- if (!consumer.process(off + i, off + i + 1, Character.toString(undecoded.charAt(i)))) {
- return false;
- }
- }
- return true;
- }
-
- private static boolean iterateRawCharacterRanges(TextRangeConsumer consumer, String undecoded, int off, boolean unicode) {
- for (int i = 0; i < undecoded.length(); i++) {
- char c = undecoded.charAt(i);
- if (unicode && c == '\\' && i < undecoded.length()-1) {
- char c2 = undecoded.charAt(i+1);
- if (c2 == 'u' && i < undecoded.length()-5) {
- try {
- char u = (char) Integer.parseInt(undecoded.substring(i+2, i+6), 16);
- if (!consumer.process(off+i, off+i+ 6, Character.toString(u))) {
- return false;
- }
- }
- catch (NumberFormatException ignore) { }
- //noinspection AssignmentToForLoopParameter
- i += 5;
- continue;
- }
- if (c2 == 'U' && i < undecoded.length()-9) {
- // note: Java has 16-bit chars, so this code will truncate characters which don't fit in 16 bits
- try {
- char u = (char) Long.parseLong(undecoded.substring(i+2, i+10), 16);
- if (!consumer.process(off+i, off+i+10, Character.toString(u))) {
- return false;
- }
- }
- catch (NumberFormatException ignore) { }
- //noinspection AssignmentToForLoopParameter
- i += 9;
- continue;
- }
- }
- if (!consumer.process(off + i, off + i + 1, Character.toString(c))) {
- return false;
- }
- }
-
- return true;
- }
-
@Override
public String toString() {
return super.toString() + ": " + getStringValue();
@@ -368,57 +339,60 @@
@Override
public boolean decode(@NotNull final TextRange rangeInsideHost, @NotNull final StringBuilder outChars) {
- final PyDocStringOwner
- docStringOwner = PsiTreeUtil.getParentOfType(myHost, PyDocStringOwner.class);
- if (docStringOwner != null && myHost.equals(docStringOwner.getDocStringExpression())) {
- outChars.append(myHost.getText(), rangeInsideHost.getStartOffset(), rangeInsideHost.getEndOffset());
- }
- else {
- myHost.iterateCharacterRanges(new TextRangeConsumer() {
- public boolean process(int startOffset, int endOffset, String value) {
- int xsectStart = Math.max(startOffset, rangeInsideHost.getStartOffset());
- int xsectEnd = Math.min(endOffset, rangeInsideHost.getEndOffset());
- if (xsectEnd > xsectStart) {
- outChars.append(value);
- }
- return endOffset < rangeInsideHost.getEndOffset();
+ for (Pair<TextRange, String> fragment : myHost.getDecodedFragments()) {
+ final TextRange encodedTextRange = fragment.getFirst();
+ final TextRange intersection = encodedTextRange.intersection(rangeInsideHost);
+ if (intersection != null && !intersection.isEmpty()) {
+ final String value = fragment.getSecond();
+ final String intersectedValue;
+ if (value.length() == 1 || value.length() == intersection.getLength()) {
+ intersectedValue = value;
}
- });
+ else {
+ final int start = Math.max(0, rangeInsideHost.getStartOffset() - encodedTextRange.getStartOffset());
+ final int end = Math.min(value.length(), start + intersection.getLength());
+ intersectedValue = value.substring(start, end);
+ }
+ outChars.append(intersectedValue);
+ }
}
return true;
}
@Override
public int getOffsetInHost(final int offsetInDecoded, @NotNull final TextRange rangeInsideHost) {
- final Ref<Integer> resultRef = Ref.create(-1);
- final Ref<Integer> indexRef = Ref.create(0);
- final Ref<Integer> lastEndOffsetRef = Ref.create(-1);
- myHost.iterateCharacterRanges(new TextRangeConsumer() {
- @Override
- public boolean process(int startOffset, int endOffset, String value) {
- if (startOffset > rangeInsideHost.getEndOffset()) {
- return false;
+ int offset = 0;
+ int endOffset = -1;
+ for (Pair<TextRange, String> fragment : myHost.getDecodedFragments()) {
+ final TextRange encodedTextRange = fragment.getFirst();
+ final TextRange intersection = encodedTextRange.intersection(rangeInsideHost);
+ if (intersection != null && !intersection.isEmpty()) {
+ final String value = fragment.getSecond();
+ final int valueLength = value.length();
+ final int intersectionLength = intersection.getLength();
+ if (valueLength == 0) {
+ return -1;
}
- lastEndOffsetRef.set(endOffset);
- if (startOffset >= rangeInsideHost.getStartOffset()) {
- final int i = indexRef.get();
- if (i == offsetInDecoded) {
- resultRef.set(startOffset);
- return false;
+ else if (valueLength == 1) {
+ if (offset == offsetInDecoded) {
+ return intersection.getStartOffset();
}
- indexRef.set(i + 1);
+ offset++;
}
- return true;
+ else {
+ if (offset + intersectionLength >= offsetInDecoded) {
+ final int delta = offsetInDecoded - offset;
+ return intersection.getStartOffset() + delta;
+ }
+ offset += intersectionLength;
+ }
+ endOffset = intersection.getEndOffset();
}
- });
- final int result = resultRef.get();
- if (result != -1) {
- return result;
}
- // We should handle the position of a character at the end of rangeInsideHost, because LeafPatcher expects it to be valid
- final int lastEndOffset = lastEndOffsetRef.get();
- if (indexRef.get() == offsetInDecoded && lastEndOffset == rangeInsideHost.getEndOffset()) {
- return lastEndOffset;
+ // XXX: According to the real use of getOffsetInHost() it should return the correct host offset for the offset in decoded at the
+ // end of the range inside host, not -1
+ if (offset == offsetInDecoded) {
+ return endOffset;
}
return -1;
}
@@ -431,23 +405,7 @@
@Override
public int valueOffsetToTextOffset(int valueOffset) {
- final Ref<Integer> offsetInDecodedRef = new Ref<Integer>(valueOffset);
- final Ref<Integer> result = new Ref<Integer>(-1);
- iterateCharacterRanges(new TextRangeConsumer() {
- public boolean process(int startOffset, int endOffset, String value) {
- if (value.length() > offsetInDecodedRef.get()) {
- result.set(startOffset + offsetInDecodedRef.get());
- return false;
- }
- offsetInDecodedRef.set(offsetInDecodedRef.get() - value.length());
- if (offsetInDecodedRef.get() == 0) {
- result.set(endOffset);
- return false;
- }
- return true;
- }
- });
- return result.get();
+ return createLiteralTextEscaper().getOffsetInHost(valueOffset, getStringValueTextRange());
}
public boolean characterNeedsEscaping(char c) {
diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java
index 57fe1a6..6a80851 100644
--- a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java
+++ b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java
@@ -15,6 +15,7 @@
*/
package com.jetbrains.python.psi.resolve;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.projectRoots.Sdk;
@@ -366,6 +367,9 @@
if (vFile != null && vFile.getLength() > 0) {
rate += 100;
}
+ for (PyResolveResultRater rater : Extensions.getExtensions(PyResolveResultRater.EP_NAME)) {
+ rate += rater.getRate(target);
+ }
}
ret.poke(target, rate);
}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java
index f5ba918..9b11d15 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java
@@ -25,16 +25,15 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
-import com.jetbrains.python.documentation.DocStringTypeReference;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.impl.PyImportedModule;
import com.jetbrains.python.psi.impl.PyPsiUtils;
-import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -190,7 +189,7 @@
public void visitPyStringLiteralExpression(PyStringLiteralExpression node) {
super.visitPyStringLiteralExpression(node);
for (PsiReference ref : node.getReferences()) {
- if (ref instanceof DocStringTypeReference && ref.isReferenceTo(oldElement)) {
+ if (ref.isReferenceTo(oldElement)) {
ref.bindToElement(newElement);
}
}
diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveClassOrFunctionProcessor.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveClassOrFunctionProcessor.java
index fe4da8e..5c22514 100644
--- a/python/src/com/jetbrains/python/refactoring/move/PyMoveClassOrFunctionProcessor.java
+++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveClassOrFunctionProcessor.java
@@ -23,6 +23,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.psi.util.QualifiedName;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.ui.UsageViewDescriptorAdapter;
import com.intellij.refactoring.util.CommonRefactoringUtil;
@@ -33,9 +34,7 @@
import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.codeInsight.imports.PyImportOptimizer;
-import com.jetbrains.python.documentation.DocStringTypeReference;
import com.jetbrains.python.psi.*;
-import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
import com.jetbrains.python.refactoring.PyRefactoringUtil;
import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
@@ -193,7 +192,7 @@
}
if (usage instanceof PyStringLiteralExpression) {
for (PsiReference ref : usage.getReferences()) {
- if (ref instanceof DocStringTypeReference && ref.isReferenceTo(oldElement)) {
+ if (ref.isReferenceTo(oldElement)) {
ref.bindToElement(newElement);
}
}
diff --git a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryExceptSurrounder.java b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryExceptSurrounder.java
index 5cdaba2..25a9f26 100644
--- a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryExceptSurrounder.java
+++ b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryExceptSurrounder.java
@@ -22,7 +22,6 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyBundle;
@@ -53,9 +52,10 @@
final PsiFile psiFile = parent.getContainingFile();
final Document document = psiFile.getViewProvider().getDocument();
- final RangeMarker rangeMarker = document.createRangeMarker(tryStatement.getTextRange());
+ final TextRange range = tryStatement.getTextRange();
+ assert document != null;
+ final RangeMarker rangeMarker = document.createRangeMarker(range);
- CodeStyleManager.getInstance(project).reformat(psiFile);
final PsiElement element = psiFile.findElementAt(rangeMarker.getStartOffset());
tryStatement = PsiTreeUtil.getParentOfType(element, PyTryExceptStatement.class);
if (tryStatement != null) {
@@ -70,7 +70,9 @@
protected TextRange getResultRange(PyTryExceptStatement tryStatement) {
final PyExceptPart part = tryStatement.getExceptParts()[0];
- return part.getStatementList().getTextRange();
+ final PyStatementList list = part.getStatementList();
+ assert list != null;
+ return list.getTextRange();
}
public String getTemplateDescription() {
diff --git a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryFinallySurrounder.java b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryFinallySurrounder.java
index 54e2c27..d457e32 100644
--- a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryFinallySurrounder.java
+++ b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryFinallySurrounder.java
@@ -17,6 +17,8 @@
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.openapi.util.TextRange;
+import com.jetbrains.python.psi.PyFinallyPart;
+import com.jetbrains.python.psi.PyStatementList;
import com.jetbrains.python.psi.PyTryExceptStatement;
/**
@@ -37,6 +39,10 @@
@Override
protected TextRange getResultRange(PyTryExceptStatement tryStatement) {
- return tryStatement.getFinallyPart().getStatementList().getTextRange();
+ final PyFinallyPart finallyPart = tryStatement.getFinallyPart();
+ assert finallyPart != null;
+ final PyStatementList statementList = finallyPart.getStatementList();
+ assert statementList != null;
+ return statementList.getTextRange();
}
}
diff --git a/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java b/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java
index 5fc0bc8..ba272c6 100644
--- a/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java
+++ b/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java
@@ -23,7 +23,6 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
-import com.intellij.openapi.ui.Messages;
import com.intellij.util.PathMappingSettings;
import com.jetbrains.python.remote.PyRemoteSdkData;
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
@@ -43,21 +42,15 @@
if (manager != null) {
ProcessHandler processHandler;
- while (true) {
- try {
- processHandler = doStartRemoteProcess(sdk, commandLine, manager, project, mappingSettings);
- break;
+ try {
+ processHandler = doStartRemoteProcess(sdk, commandLine, manager, project, mappingSettings);
+ }
+ catch (ExecutionException e) {
+ final Application application = ApplicationManager.getApplication();
+ if (application != null && (application.isUnitTestMode() || application.isHeadlessEnvironment())) {
+ throw new RuntimeException(e);
}
- catch (ExecutionException e) {
- final Application application = ApplicationManager.getApplication();
- if (application != null && (application.isUnitTestMode() || application.isHeadlessEnvironment())) {
- throw new RuntimeException(e);
- }
- if (Messages.showYesNoDialog(e.getMessage() + "\nTry again?", "Can't Run Remote Interpreter", Messages.getErrorIcon()) ==
- Messages.NO) {
- throw new ExecutionException("Can't run remote python interpreter: " + e.getMessage(), e);
- }
- }
+ throw new ExecutionException("Can't run remote python interpreter: " + e.getMessage(), e);
}
ProcessTerminatedListener.attach(processHandler);
return processHandler;
diff --git a/python/src/com/jetbrains/python/spellchecker/PythonSpellcheckerStrategy.java b/python/src/com/jetbrains/python/spellchecker/PythonSpellcheckerStrategy.java
index 4a0a59d..b24e53c 100644
--- a/python/src/com/jetbrains/python/spellchecker/PythonSpellcheckerStrategy.java
+++ b/python/src/com/jetbrains/python/spellchecker/PythonSpellcheckerStrategy.java
@@ -15,6 +15,7 @@
*/
package com.jetbrains.python.spellchecker;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.spellchecker.inspections.PlainTextSplitter;
@@ -26,7 +27,6 @@
import com.jetbrains.python.inspections.PyStringFormatParser;
import com.jetbrains.python.psi.PyBinaryExpression;
import com.jetbrains.python.psi.PyStringLiteralExpression;
-import com.jetbrains.python.psi.impl.PyStringLiteralExpressionImpl;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -41,9 +41,11 @@
Splitter splitter = PlainTextSplitter.getInstance();
String text = element.getText();
if (text.indexOf('\\') >= 0) {
- MyTextRangeConsumer textRangeConsumer = new MyTextRangeConsumer(element, consumer);
- ((PyStringLiteralExpressionImpl) element).iterateCharacterRanges(textRangeConsumer);
- textRangeConsumer.processCurrentToken(); // process last token
+ for (Pair<TextRange, String> fragment : element.getDecodedFragments()) {
+ final String value = fragment.getSecond();
+ consumer.consumeToken(element, value, false, fragment.getFirst().getStartOffset(), TextRange.allOf(value),
+ PlainTextSplitter.getInstance());
+ }
}
else if (text.startsWith("u") || text.startsWith("U") || text.startsWith("r") || text.startsWith("R") ||
text.startsWith("b") || text.startsWith("B")) {
@@ -57,40 +59,6 @@
consumer.consumeToken(element, splitter);
}
}
-
- private static class MyTextRangeConsumer implements PyStringLiteralExpressionImpl.TextRangeConsumer {
- private final StringBuilder myCurrentToken = new StringBuilder();
- private final PyStringLiteralExpression myElement;
- private final TokenConsumer myTokenConsumer;
- private int myTokenStart;
-
- public MyTextRangeConsumer(PyStringLiteralExpression element, TokenConsumer tokenConsumer) {
- myElement = element;
- myTokenConsumer = tokenConsumer;
- }
-
- @Override
- public boolean process(int startOffset, int endOffset, String value) {
- if (endOffset == startOffset + 1) {
- if (myCurrentToken.length() == 0) {
- myTokenStart = startOffset;
- }
- myCurrentToken.append(value);
- }
- else {
- if (myCurrentToken.length() > 0) {
- processCurrentToken();
- myCurrentToken.setLength(0);
- }
- }
- return true;
- }
-
- private void processCurrentToken() {
- String token = myCurrentToken.toString();
- myTokenConsumer.consumeToken(myElement, token, false, myTokenStart, TextRange.allOf(token), PlainTextSplitter.getInstance());
- }
- }
}
private static class FormatStringTokenizer extends Tokenizer<PyStringLiteralExpression> {
diff --git a/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java b/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
index ef16a65..39e4e96 100644
--- a/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
+++ b/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
@@ -106,9 +106,10 @@
return cmd;
}
- private void setWorkingDirectory(@NotNull final GeneralCommandLine cmd) {
- if (!StringUtil.isEmptyOrSpaces(myConfiguration.getWorkingDirectory())) {
- cmd.setWorkDirectory(myConfiguration.getWorkingDirectory());
+ protected void setWorkingDirectory(@NotNull final GeneralCommandLine cmd) {
+ final String workingDirectory = myConfiguration.getWorkingDirectory();
+ if (!StringUtil.isEmptyOrSpaces(workingDirectory)) {
+ cmd.setWorkDirectory(workingDirectory);
}
else if (myConfiguration instanceof AbstractPythonTestRunConfiguration) {
final String folderName = ((AbstractPythonTestRunConfiguration)myConfiguration).getFolderName();
diff --git a/python/src/com/jetbrains/python/testing/PythonTestConfigurationProducer.java b/python/src/com/jetbrains/python/testing/PythonTestConfigurationProducer.java
index 3875cd3..8c28e08 100644
--- a/python/src/com/jetbrains/python/testing/PythonTestConfigurationProducer.java
+++ b/python/src/com/jetbrains/python/testing/PythonTestConfigurationProducer.java
@@ -18,6 +18,7 @@
import com.google.common.collect.Sets;
import com.intellij.execution.Location;
import com.intellij.execution.actions.ConfigurationContext;
+import com.intellij.execution.actions.ConfigurationFromContext;
import com.intellij.execution.actions.RunConfigurationProducer;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.facet.Facet;
@@ -39,6 +40,7 @@
import com.jetbrains.python.PythonModuleTypeBase;
import com.jetbrains.python.facet.PythonFacetSettings;
import com.jetbrains.python.psi.*;
+import com.jetbrains.python.run.PythonRunConfigurationProducer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -254,4 +256,8 @@
return PythonUnitTestUtil.getTestCaseClassesFromFile(pyFile);
}
+ @Override
+ public boolean isPreferredConfiguration(ConfigurationFromContext self, ConfigurationFromContext other) {
+ return other.isProducedBy(PythonTestConfigurationProducer.class) || other.isProducedBy(PythonRunConfigurationProducer.class);
+ }
}
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/testing/PythonUnitTestUtil.java b/python/src/com/jetbrains/python/testing/PythonUnitTestUtil.java
index d0b4ea1..9394143 100644
--- a/python/src/com/jetbrains/python/testing/PythonUnitTestUtil.java
+++ b/python/src/com/jetbrains/python/testing/PythonUnitTestUtil.java
@@ -93,7 +93,7 @@
}
}
for (PyFunction cls : file.getTopLevelFunctions()) {
- if (isTestCaseFunction(cls)) {
+ if (isTestCaseFunction(cls, false)) {
result.add(cls);
}
}
@@ -115,9 +115,9 @@
}
if (checkAssert) {
boolean hasAssert = hasAssertOrYield(function.getStatementList());
- if (!hasAssert) return false;
+ if (hasAssert) return true;
}
- return true;
+ return false;
}
private static boolean hasAssertOrYield(PyStatementList list) {
diff --git a/python/src/com/jetbrains/python/testing/doctest/PythonDocTestConfigurationProducer.java b/python/src/com/jetbrains/python/testing/doctest/PythonDocTestConfigurationProducer.java
index cfa2be7..e3eef29 100644
--- a/python/src/com/jetbrains/python/testing/doctest/PythonDocTestConfigurationProducer.java
+++ b/python/src/com/jetbrains/python/testing/doctest/PythonDocTestConfigurationProducer.java
@@ -21,6 +21,8 @@
import com.intellij.execution.Location;
import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiRecursiveElementVisitor;
@@ -85,4 +87,10 @@
}
}
}
+
+ @Override
+ protected boolean isTestFolder(@NotNull VirtualFile virtualFile, @NotNull Project project) {
+ return false;
+ }
+
}
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/testing/pytest/PyTestRunnableScriptFilter.java b/python/src/com/jetbrains/python/testing/pytest/PyTestRunnableScriptFilter.java
deleted file mode 100644
index 036663b..0000000
--- a/python/src/com/jetbrains/python/testing/pytest/PyTestRunnableScriptFilter.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.testing.pytest;
-
-import com.intellij.execution.Location;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.projectRoots.Sdk;
-import com.intellij.psi.PsiFile;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyFile;
-import com.jetbrains.python.psi.PyFunction;
-import com.jetbrains.python.psi.PyRecursiveElementVisitor;
-import com.jetbrains.python.run.RunnableScriptFilter;
-import com.jetbrains.python.sdk.PythonSdkType;
-import com.jetbrains.python.testing.PythonTestConfigurationsModel;
-import com.jetbrains.python.testing.TestRunnerService;
-import com.jetbrains.python.testing.VFSTestFrameworkListener;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author yole
- */
-public class PyTestRunnableScriptFilter implements RunnableScriptFilter {
- public boolean isRunnableScript(PsiFile script, @NotNull Module module, Location location) {
- return isPyTestInstalled(module) && isPyTestScript(script) &&
- TestRunnerService.getInstance(module).getProjectConfiguration().
- equals(PythonTestConfigurationsModel.PY_TEST_NAME);
- }
-
- private static boolean isPyTestInstalled(Module module) {
- // TODO[yole] add caching to avoid disk I/O in findPyTestRunner()?
- final Sdk sdk = PythonSdkType.findPythonSdk(module);
- return sdk != null && VFSTestFrameworkListener.getInstance().isPyTestInstalled(sdk);
- }
-
- public static boolean isPyTestScript(PsiFile script) {
- if (!(script instanceof PyFile)) {
- return false;
- }
- PyTestVisitor testVisitor = new PyTestVisitor();
- script.accept(testVisitor);
- return testVisitor.isTestsFound();
- }
-
- private static class PyTestVisitor extends PyRecursiveElementVisitor {
- private boolean myTestsFound = false;
-
- public boolean isTestsFound() {
- return myTestsFound;
- }
-
- @Override
- public void visitPyFunction(PyFunction node) {
- super.visitPyFunction(node);
- String name = node.getName();
- if (name != null && name.startsWith("test")) {
- myTestsFound = true;
- }
- }
-
- @Override
- public void visitPyClass(PyClass node) {
- super.visitPyClass(node);
- String name = node.getName();
- if (name != null && name.startsWith("Test")) {
- myTestsFound = true;
- }
- }
- }
-}
diff --git a/python/testData/completion/epydocParamTag.py b/python/testData/completion/epydocParamTag.py
index 6323111..e74df8d 100644
--- a/python/testData/completion/epydocParamTag.py
+++ b/python/testData/completion/epydocParamTag.py
@@ -1,2 +1,2 @@
def foo(bar):
- """ @param <caret> """
\ No newline at end of file
+ """ @param b<caret> """
\ No newline at end of file
diff --git a/python/testData/completion/identifiersInPlainDocstring.after.py b/python/testData/completion/identifiersInPlainDocstring.after.py
deleted file mode 100644
index 440570b..0000000
--- a/python/testData/completion/identifiersInPlainDocstring.after.py
+++ /dev/null
@@ -1,2 +0,0 @@
-def foo(bar):
- """ Variable bar """
\ No newline at end of file
diff --git a/python/testData/inspections/PyMethodMayBeStaticInspection/decorated.py b/python/testData/inspections/PyMethodMayBeStaticInspection/decorated.py
new file mode 100644
index 0000000..c16da1e
--- /dev/null
+++ b/python/testData/inspections/PyMethodMayBeStaticInspection/decorated.py
@@ -0,0 +1,15 @@
+def bar(f):
+ def wrapper(self, *args, **kwargs):
+ print('running {cls}.{method}'.format(cls=type(self).__name__,
+ method=f.__name__))
+ return f(self, *args, **kwargs)
+ return wrapper
+
+
+class C(object):
+ @bar
+ def foo(self): # False positive: self is used by @bar
+ return 'foo'
+
+
+C().foo()
\ No newline at end of file
diff --git a/python/testData/inspections/spelling/ignoreEscapeSequence.py b/python/testData/inspections/spelling/ignoreEscapeSequence.py
index 3bd9965..95e8df4 100644
--- a/python/testData/inspections/spelling/ignoreEscapeSequence.py
+++ b/python/testData/inspections/spelling/ignoreEscapeSequence.py
@@ -1 +1,2 @@
-print "foo\nsomething"
\ No newline at end of file
+print "foo\nsomething"
+print """foo\n<TYPO descr="Typo: In word 'brbrbr'">brbrbr</TYPO>"""
diff --git a/python/testData/psi/NotClosedBraceDict.py b/python/testData/psi/NotClosedBraceDict.py
new file mode 100644
index 0000000..9a72624
--- /dev/null
+++ b/python/testData/psi/NotClosedBraceDict.py
@@ -0,0 +1,3 @@
+a = {
+ 'b': 'c',
+ ]
\ No newline at end of file
diff --git a/python/testData/psi/NotClosedBraceDict.txt b/python/testData/psi/NotClosedBraceDict.txt
new file mode 100644
index 0000000..1222ea3
--- /dev/null
+++ b/python/testData/psi/NotClosedBraceDict.txt
@@ -0,0 +1,24 @@
+PyFile:NotClosedBraceDict.py
+ PyAssignmentStatement
+ PyTargetExpression: a
+ PsiElement(Py:IDENTIFIER)('a')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PyDictLiteralExpression
+ PsiElement(Py:LBRACE)('{')
+ PsiWhiteSpace('\n ')
+ PyKeyValueExpression
+ PyStringLiteralExpression: b
+ PsiElement(Py:SINGLE_QUOTED_STRING)(''b'')
+ PsiElement(Py:COLON)(':')
+ PsiWhiteSpace(' ')
+ PyStringLiteralExpression: c
+ PsiElement(Py:SINGLE_QUOTED_STRING)(''c'')
+ PsiElement(Py:COMMA)(',')
+ PsiErrorElement:'}' expected
+ <empty list>
+ PsiWhiteSpace('\n ')
+ PsiElement(Py:RBRACKET)(']')
+ PsiErrorElement:Statement expected, found Py:RBRACKET
+ <empty list>
\ No newline at end of file
diff --git a/python/testData/psi/NotClosedBraceSet.py b/python/testData/psi/NotClosedBraceSet.py
new file mode 100644
index 0000000..71817f2
--- /dev/null
+++ b/python/testData/psi/NotClosedBraceSet.py
@@ -0,0 +1 @@
+a = {'b',]
\ No newline at end of file
diff --git a/python/testData/psi/NotClosedBraceSet.txt b/python/testData/psi/NotClosedBraceSet.txt
new file mode 100644
index 0000000..95b97f0
--- /dev/null
+++ b/python/testData/psi/NotClosedBraceSet.txt
@@ -0,0 +1,17 @@
+PyFile:NotClosedBraceSet.py
+ PyAssignmentStatement
+ PyTargetExpression: a
+ PsiElement(Py:IDENTIFIER)('a')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:EQ)('=')
+ PsiWhiteSpace(' ')
+ PySetLiteralExpression
+ PsiElement(Py:LBRACE)('{')
+ PyStringLiteralExpression: b
+ PsiElement(Py:SINGLE_QUOTED_STRING)(''b'')
+ PsiElement(Py:COMMA)(',')
+ PsiErrorElement:'}' expected
+ <empty list>
+ PsiElement(Py:RBRACKET)(']')
+ PsiErrorElement:Statement expected, found Py:RBRACKET
+ <empty list>
\ No newline at end of file
diff --git a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams.py b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams.py
deleted file mode 100644
index 7cdd655..0000000
--- a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams.py
+++ /dev/null
@@ -1,10 +0,0 @@
-__author__ = 'ktisha'
-
-def foo(x):
- return x
-
-class A():
-
- @accepts(int, int)
- def my_<caret>method(self):
- print "Smth"
\ No newline at end of file
diff --git a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams_after.py b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams_after.py
deleted file mode 100644
index 21293a9..0000000
--- a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams_after.py
+++ /dev/null
@@ -1,11 +0,0 @@
-__author__ = 'ktisha'
-
-def foo(x):
- return x
-
-class A():
-
- @staticmethod
- @accepts(int, int)
- def my_<caret>method():
- print "Smth"
\ No newline at end of file
diff --git a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco.py b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco.py
deleted file mode 100644
index dded2b0..0000000
--- a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco.py
+++ /dev/null
@@ -1,10 +0,0 @@
-__author__ = 'ktisha'
-
-def foo(x):
- return x
-
-class A():
-
- @my_deco
- def my_<caret>method(self):
- print "Smth"
\ No newline at end of file
diff --git a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco_after.py b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco_after.py
deleted file mode 100644
index 36607a4..0000000
--- a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco_after.py
+++ /dev/null
@@ -1,11 +0,0 @@
-__author__ = 'ktisha'
-
-def foo(x):
- return x
-
-class A():
-
- @staticmethod
- @my_deco
- def my_method():
- print "Smth"
\ No newline at end of file
diff --git a/python/testData/surround/SurroundWithTryExcept.py b/python/testData/surround/SurroundWithTryExcept.py
index faee07e..ee6e2cb 100644
--- a/python/testData/surround/SurroundWithTryExcept.py
+++ b/python/testData/surround/SurroundWithTryExcept.py
@@ -1,2 +1,2 @@
def foo():
- <selection>print "hello"</selection>
\ No newline at end of file
+ pr<caret>int "hello"
\ No newline at end of file
diff --git a/python/testData/surround/SurroundWithTryExcept_after.py b/python/testData/surround/SurroundWithTryExcept_after.py
index 54b20bc..ae244ff 100644
--- a/python/testData/surround/SurroundWithTryExcept_after.py
+++ b/python/testData/surround/SurroundWithTryExcept_after.py
@@ -2,4 +2,4 @@
try:
print "hello"
except:
- <selection>pass</selection>
\ No newline at end of file
+ <selection>pass</selection>
diff --git a/python/testSrc/com/jetbrains/python/PyStringLiteralTest.java b/python/testSrc/com/jetbrains/python/PyStringLiteralTest.java
index 7f5b08a..3933584 100644
--- a/python/testSrc/com/jetbrains/python/PyStringLiteralTest.java
+++ b/python/testSrc/com/jetbrains/python/PyStringLiteralTest.java
@@ -15,6 +15,7 @@
*/
package com.jetbrains.python;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.LiteralTextEscaper;
import com.intellij.psi.PsiFile;
@@ -64,19 +65,54 @@
assertEquals(-1, escaper.getOffsetInHost(4, fooOnly));
}
- public void testIterateCharacterRanges() {
- final PyStringLiteralExpression expr = createLiteralFromText("'\\nfoo' 'bar'");
+ public void testEscaperOffsetInSingleCharString() {
+ final PyStringLiteralExpression expr = createLiteralFromText("'c'");
assertNotNull(expr);
- final List<String> characters = new ArrayList<String>();
- expr.iterateCharacterRanges(new PyStringLiteralExpression.TextRangeConsumer() {
- @Override
- public boolean process(int startOffset, int endOffset, String value) {
- characters.add(value);
- return true;
- }
- });
- final List<String> expected = Arrays.asList("\n", "f", "o", "o", "b", "a", "r");
- assertSameElements(characters, expected);
+ final LiteralTextEscaper<? extends PsiLanguageInjectionHost> escaper = expr.createLiteralTextEscaper();
+ final TextRange range = TextRange.create(1, 2);
+ assertEquals(1, escaper.getOffsetInHost(0, range));
+ assertEquals(2, escaper.getOffsetInHost(1, range));
+ assertEquals(-1, escaper.getOffsetInHost(2, range));
+ }
+
+ public void testEscaperOffsetInSingleEscapedCharString() {
+ final PyStringLiteralExpression expr = createLiteralFromText("'\\n'");
+ assertNotNull(expr);
+ final LiteralTextEscaper<? extends PsiLanguageInjectionHost> escaper = expr.createLiteralTextEscaper();
+ final TextRange range = TextRange.create(1, 3);
+ assertEquals(1, escaper.getOffsetInHost(0, range));
+ assertEquals(3, escaper.getOffsetInHost(1, range));
+ assertEquals(-1, escaper.getOffsetInHost(2, range));
+ }
+
+ public void testIterateCharacterRanges() {
+ assertSameElements(getCharacterRanges("'\\nfoo' 'bar'"),
+ Arrays.asList("\n", "foo", "bar"));
+ }
+
+ public void testIterateEscapedBackslash() {
+ assertSameElements(getCharacterRanges("'''\n" +
+ "foo.\\\\\n" +
+ "bar\n" +
+ "'''\n"),
+ Arrays.asList("\nfoo.", "\\", "\nbar\n"));
+ }
+
+ public void testEscaperOffsetInEscapedBackslash() {
+ final PyStringLiteralExpression expr = createLiteralFromText("'XXX foo.\\\\bar YYY'");
+ assertNotNull(expr);
+ final LiteralTextEscaper<? extends PsiLanguageInjectionHost> escaper = expr.createLiteralTextEscaper();
+ final TextRange range = TextRange.create(5, 14);
+ assertEquals(5, escaper.getOffsetInHost(0, range));
+ assertEquals(6, escaper.getOffsetInHost(1, range));
+ assertEquals(7, escaper.getOffsetInHost(2, range));
+ assertEquals(8, escaper.getOffsetInHost(3, range));
+ assertEquals(9, escaper.getOffsetInHost(4, range));
+ assertEquals(11, escaper.getOffsetInHost(5, range));
+ assertEquals(12, escaper.getOffsetInHost(6, range));
+ assertEquals(13, escaper.getOffsetInHost(7, range));
+ assertEquals(14, escaper.getOffsetInHost(8, range));
+ assertEquals(-1, escaper.getOffsetInHost(9, range));
}
private static String decodeRange(PyStringLiteralExpression expr, TextRange range) {
@@ -100,4 +136,14 @@
assertEquals("b\\n", createLiteralFromText("ur'\\u0062\\n'").getStringValue());
assertEquals("\\8", createLiteralFromText("'\\8'").getStringValue());
}
+
+ private List<String> getCharacterRanges(String text) {
+ final PyStringLiteralExpression expr = createLiteralFromText(text);
+ assertNotNull(expr);
+ final List<String> characters = new ArrayList<String>();
+ for (Pair<TextRange, String> fragment : expr.getDecodedFragments()) {
+ characters.add(fragment.getSecond());
+ }
+ return characters;
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/PySurroundWithTest.java b/python/testSrc/com/jetbrains/python/PySurroundWithTest.java
index b2a1292..5f49581 100644
--- a/python/testSrc/com/jetbrains/python/PySurroundWithTest.java
+++ b/python/testSrc/com/jetbrains/python/PySurroundWithTest.java
@@ -35,7 +35,7 @@
doTest(new PyWithWhileSurrounder());
}
- public void _testSurroundWithTryExcept() throws Exception {
+ public void testSurroundWithTryExcept() throws Exception {
doTest(new PyWithTryExceptSurrounder());
}
diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
index 4f93cca..da7888e 100644
--- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
@@ -15,9 +15,12 @@
*/
package com.jetbrains.python;
+import com.google.common.collect.Lists;
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
+import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.jetbrains.python.documentation.DocStringFormat;
import com.jetbrains.python.documentation.PyDocumentationSettings;
import com.jetbrains.python.fixtures.PyTestCase;
@@ -387,8 +390,10 @@
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(myFixture.getModule());
settings.setFormat(DocStringFormat.PLAIN);
myFixture.configureByFile("completion/identifiersInPlainDocstring.py");
- myFixture.completeBasic();
- myFixture.checkResultByFile("completion/identifiersInPlainDocstring.after.py");
+ final LookupElement[] elements = myFixture.completeBasic();
+ assertNotNull(elements);
+ assertContainsElements(Lists.newArrayList(elements),
+ LookupElementBuilder.create("bar").withAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE));
}
public void testPep328Completion() { // PY-3409
diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java
index 669ac3d..9f612a2 100644
--- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java
@@ -430,6 +430,14 @@
doTest();
}
+ public void testNotClosedBraceDict() {
+ doTest();
+ }
+
+ public void testNotClosedBraceSet() {
+ doTest(LanguageLevel.PYTHON33);
+ }
+
public void doTest(LanguageLevel languageLevel) {
LanguageLevel prev = myLanguageLevel;
myLanguageLevel = languageLevel;
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyMethodMayBeStaticInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyMethodMayBeStaticInspectionTest.java
index ea40830..885f043 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyMethodMayBeStaticInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyMethodMayBeStaticInspectionTest.java
@@ -15,6 +15,7 @@
*/
package com.jetbrains.python.inspections;
+import com.intellij.testFramework.TestDataPath;
import com.jetbrains.python.PythonTestUtil;
import com.jetbrains.python.fixtures.PyTestCase;
@@ -23,6 +24,7 @@
/**
* User: ktisha
*/
+@TestDataPath("$CONTENT_ROOT/../testData/inspections/PyMethodMayBeStaticInspection/")
public class PyMethodMayBeStaticInspectionTest extends PyTestCase {
public void testTruePositive() {
@@ -65,6 +67,10 @@
doTest();
}
+ public void testDecorated() {
+ doTest();
+ }
+
public void testOverwrittenMethod() {
doTest();
}
diff --git a/python/testSrc/com/jetbrains/python/quickFixes/PyMakeMethodStaticQuickFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/PyMakeMethodStaticQuickFixTest.java
index 310c211..835e6ed 100644
--- a/python/testSrc/com/jetbrains/python/quickFixes/PyMakeMethodStaticQuickFixTest.java
+++ b/python/testSrc/com/jetbrains/python/quickFixes/PyMakeMethodStaticQuickFixTest.java
@@ -36,14 +36,6 @@
doQuickFixTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static"));
}
- public void testFunctionWithDeco() {
- doQuickFixTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static"));
- }
-
- public void testDecoWithParams() {
- doQuickFixTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static"));
- }
-
public void testNoSelf() {
doQuickFixTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static"));
}