Snapshot ae49fc0ed43dd87b534931e62fceae2bcac4fdf1 from idea/134.1445 of git://git.jetbrains.org/idea/community.git
ae49fc0: scala 0.32.(593|562|558|550) and AngularJS 0.1.(8|9) marked as incompatible
c3a2e25: Remove unused variable
fe44c93: Multicaret XML: fix type handler for multicaret mode
94108b1: IDEA-121711 Breakpoints dialog: cannot select items in Field Watchpoints section
4933fb4: Add AngularJS plugin
c0ee8f0: IntelliJ Idea 13.1 artworks
95977a0: new inference: cleanup
b3b99f4: ensure order
e9d3421: update button on installed plugins panel
5237f29: IDEA-121151 Breakpoints dialog: Group by Package / File shows exception items in wrong branch
6289c57: show information about multiple carets in status bar (IDEA-80056)
9ac9b91: add getCaretCount method to caret model API (IDEA-80056)
37b836c: WEB-11122 we cannot trust editor width — it could be 0 in case of soft wrap even if editor has text
ad2e3a9: nashorn: frames view — correct presentation of stack frame (function name is not yet displayed)
35fd0fc: cleanup
a433603: Use new icons and fgs
f9e15e0: CPP-6: Parameter info highlighting is messed up + review CR-IC-4631
d158a03: editorPaintStart useless in our case
d22cffe: don't paint in the overlapped region
3181d9a: CR-IC-4638 EvaluateInConsoleFromTreeAction
aa9d729: refactoring branch actions
367266a: style: sort hg reference names in getNamesWithoutHashes, unnecessary ui model creation removed
f0aba00: style: ternary operator used instead of several if-statements; comment added; unnecessary pool thread removed
58d9042: IDEA-121096 The ability to delete Mercurial bookmark
1a11673: IDEA-109794 ability to push mercurial bookmark
e4edbe9: hg action dialog refactoring
d61ace7: optimization broke code (IDEA-118426)
0da53a2: add new plugins icons
fe4a2a0: plugin update icon
9f5335b: plugin restart icon
24aab3b: plugin icon with JB logo
43e5b58: IDEA-121589 Breakpoints dialog: breakpoint categories should be present in a fixed order
f1f1141: IDEA-121675 Nashorn: Debug: RunToCursor is always disabled when js file is active
5b29ebf: Merge remote-tracking branch 'origin/master'
6893d29: revert
21068c7: scene builder: embedder
14de5df: Merge branch 'python-fixes'
7a968d0: IDEA-121642 Breakpoints dialog: closing "Disabled until" hides preview
b3a39df: caret listeners API change (IDEA-80056)
d98f5f7: IDEA-103517 diff: fix diff invocation from history tab
de02a90: revert incorrect change: BuildManager was not notified about files changes at all
e3f3e5f: notnull
6b3a754: cleanup
39bfb97: notnull
0fdd39a: CAPACITY inlined
337138e: CR-IC-4638 we must use "XDebugger", but not "Debugger"
1f2dd56: cleanup
33b0145: IDEA-121675 Nashorn: Debug: RunToCursor is always disabled when js file is active
f4d0239: fix exception at completion when multiple carets are enabled (IDEA-80056)
bc22d75: Compare sys.path roots by virtual file, not by filename because of *.egg archives
90bd285: Extracted getSdkRootVirtualFile()
0eab6fd: test framework: refresh module file
0c1cf4d: Cleanup (pointless exceptions; field extracted; arrangement)
b5a2bae: Cleanup (unused class)
5455508: Cleanup (pointless exceptions dropped)
bc72137: cleanup
3ff0739: NotNull
911290e: cleanup
b770509: cleanup
7d78ad3: cleanup
effe895: cleanup
126f4a0: cleanup
0e49f4a: anonymous -> lambda/method ref: highlight as unused symbol new ClassReference
9860e6b: migration inspection: assign weak warning to produce annoyance
380c7a9: testdata for IDEA-121661
0fa7d08: IDEA-121658 Java 1.8: "Replace with forEach" quick fix is not suggested if for statement is not surrounded with braces
c692398: Local History change temporarily reverted
803d865: IDEA-121640 Breakpoints conversion: conditions and log message languages all turn to Java
d1194fb: IDEA-121643 Breakpoints conversion: exception breakpoint dependencies are lost
95069e7: IDEA-121644 Breakpoints conversion: wildcard method breakpoints get Method entry = Method exit = true
02387b0: IDEA-121632 DomStubBuilder#getStubVersion does not use DomFileDescription#getStubVersion
01a42e5: IDEA-121632 DomStubBuilder#getStubVersion does not use DomFileDescription#getStubVersion
d05d6cd: IDEA-121555 github: get host from url before comparison
314a555: Storyboard format
8181cdb: IDEA-82129 diff: fix synchronized scrolling in merge dialog for left-middle panels
7d76faf: diff: replace Pair by container class
6baec97: repeatCount mostly done
9f2cf02: cleanup — inline
5ff9d4f: improvements for multi-caret implementation of column mode (IDEA-80056)
46208da: EA-53845 added logging
fdecf55: IDEA-121409, IDEA-120908 revert GrReassignedInClosureLocalVariableInspection back to previous state. So it doesn't check plain assignments to locals
9b9ffdb: Merge branch 'master' of git.labs.intellij.net:idea/community
f2d2e79: IDEA-120027 - Import Git-cloud apps from sources - refactor out account selection panel
121f738: IDEA-120027 - Import Git-cloud apps from sources - refactor out deployment detector
989fa1b: IDEA-121635 Injected fragment editor fails with \r\n in text
cc11811: Fix cloning sdk additional data.
7cfb673: Merge remote-tracking branch 'origin/master'
f30ac9d: Merge remote-tracking branch 'origin/master'
e31638a: IDEA-121621 Java 1.8: "Replace with collect" quick fix inserts unresolved method reference
1ae653c: Fix update of terminal input action wrapper.
fb14201: IDEA-116760 Mousing over "tool popup" button causes funny behavior
ece8311: file and doc mod stamps should be equal after save
e30e9ff: EA-53865 - assert: CachedValueProvider$Result.<init>
b5deb1d: Merge remote-tracking branch 'origin/master'
94ae901: PY-12178 Support pull up / push down for properties
27fb3a4: Local History fix: load file children on fileCreated event
5de8d20: a test for IDEA-121301 Setting a breakpoint after navigation to a folded method
a337747: use origin fqn
2a60f15: support ColorUIResource
16fa597: Merge remote-tracking branch 'origin/master'
6dd7d9d: parameter info: proper highlighting for text with XML escaped chars, e.g "map<string, int> &x" +review CR-IC
a3141a4: Merge branch 'python-fixes'
c6947e3: IDEA-108454 (test added)
7ba0d53: Merge remote-tracking branch 'origin/master'
5b6bfba: Disable default breakpoints in env debugger tests.
de2bcc9: Better logging in debugger communication.
f65481f: ResumeAction -> DumbAware
5312f17: IDEA-121301 Setting a breakpoint after navigation to a folded method
b82ea0b: updater: use system look&feel
76b0d68: CR-IU-615 (reworked)
09d9083: WI-22345 Fragment editor: typing causes Throwable at CompletionAssertions.assertCommitSuccessful()
65e4c34: Merge remote-tracking branch 'origin/master'
53752af: fixed PY-12321 PyCharm fails to auto-complete inherited PyQt methods
93eaeb4: Merge remote-tracking branch 'origin/master'
0a93c40: IDEA-121551 please sign runnerw.exe and commit
ec8c8eb: Breakpoint remove should be executed in write action like breakpoint add in XDebuggerTestUtil.
49a5a3f: don't duplicate symlink in suggested interpreter path
f673815: Fix creation of remote sdk in tests.
7a6a957: fix entities resolve without root tag
bd73c79: completion for html5 entities without root tag
41aaf52: #WEB-11032 fixed
9483000: external build: added API to allow plugins extend external build launcher classpath
465090e: Storyboard format
53d95f8: fetch commandLine from processHandler instance if possible
329b1a7: Merge remote-tracking branch 'origin/master'
dd2e76a: PY-12178 Support pull up / push down for properties
550a7e4: EvaluateInConsole
62cf3bb: ActionUtil.getActions
b01a8f1: use SmartList
f95d39d: Merge remote-tracking branch 'origin/master'
b7dca13: added browse interpreter button to create virtual env dialog
64fccff: IDEA-121378 Groovy: inspections: Access to untyped expression reports this and super
1b0f4e8: IDEA-121420 ctrl+b on "def" keyword of a variable without explicit type with initializer should navigate to inferred type
ed39848: IDEA-121140 format spock tables in the end of a file
f2fea0a: external build: added API to prepare custom java compilation task and provide default options for java compiler
0203ec8: Merge remote-tracking branch 'origin/master'
5acf645: Merge remote-tracking branch 'origin/master'
18dbd58: Merge remote-tracking branch 'origin/master'
f8f3d97: lambda: do not try to annotate super method with Nullable from lambda body (IDEA-120205) annotation for super methods was removed by cdr
a4977be: lambda/method refs: provide super class navigation - ctrl-u/line markers (IDEA-120160)
f1dac13: Deprecated remote sdk api. Old legacy classes leaved for compatibility.
4a4d94f: Merge remote-tracking branch 'origin/master'
59525f3: prepared copy of log4j before exec updater to avoid similar issue: WEB-11207 Patch to 8.0 build 134.1361 fails on Win 8.1
179bdc5: support null-values
fe93f3f: Query only the first result of super and overring method searches for performance resaons
6b1189e: more diagnostics for EA-50865 - assert: CachedValueProvider$Result.<init>
5396644: IDEA-121387 Breakpoints dialog: Exception breakpoints: no language chooser for Condition
279b7c3: EA-52976 - assert: CodeFoldingManagerImpl.releaseFoldings
00dbd95: Reuse resolve context with type eval context from the current inspection session for performance reasons
5313d0b: WI-14345 Dictionary: Missing Word "Fundraising"
f4d98a3: IDEA-121505 Breakpoint properties popup: More link does not work if over tool window splitter
fa27e1a: IDEA-121508 Breakpoints in JSP scriptlets are ignored
957b622: CR-IC-4621 allow evaluation in global context (without suspend context)
363a27a: overrides
9ef0155: finalize
ad6c95a: cleanup — move DisabledActionHandler to platform +review
e98cb45: cleanup
19adc49: cleanup
539e45a: Multicaret: fix tests
ede0620: fixed memory leak
6b8002e: Cache return types of callables using TypeEvalContext.getReturnType()
9ca3e42: IDEA-121582 (less spam in log)
b9b76dc: java: type annotations
b428981: java: shorten references after refactoring
d728fd7: IDEA-121518 Cannot edit files in IDEA after project opening: initial folding in opening thread, assertions relaxed
5ed9d91: better diagnostics
b1ae53c: javadoc
2691cb0: external build: ignore irrelevant messages in stderr of javac server (e.g. warnings from log4j)
a487452: continue WEB-10187 inspect objects in console
1a5af0d: more correct and concrete javadoc — it is NOT text, it is just highlighting
fc8c136: IDEA-121531 False positive for "Named arguments are not allowed inside index operations"
7a0eff4: external build: extracted extension point to support custom java compilers
0c6f4d1: don't display expanders on disabled components
c34a068: Merge remote-tracking branch 'origin/master'
a71ff7a: Propose to launch vagrant instance on connection to non-running vagrant remote host (PY-8751).
2905258: NotNull annotation for parent component
ea5f0a5: no "loading components" progress for default project
80d6e1f: new inference: use site substitutor during return constraints processing (red code in Collectors)
b55527a: testdata for IDEA-118965
0cb0127: IDEA-121379 ("Remove braces from if statement" is not available on "if" keyword and condition of if-else construct)
2e88d04: revert optimization because it does not optimize
d4883f5: rebuild list on EDT only
139374a: quick evaluate should allow evaluation in global context (without suspend context)
9051157: cleanup
3419368: init WEB-10187 inspect objects in console
14490aa: overrides
f9eaaef: IDEA-115491 Fragment editor > Save as: provide default directory
a2007d9: IDEA-115490 Fragment editor > Save as: forbidden default name
282ebd2: FormatterTestCase should be available to plugin developers
c4ee509: IDEA-121553 Converted field and exception breakpoints are not available to user
60dfeb6: EA-41231 (better diagnostic)
cec4bb0: show options in create new project instead of show dialog
851c599: fix highlighter update on FileContentUtil.reparseFiles()
842cb01: avoid PSI tree change listener leaks in breakpoint popup
7e61326: avoid PSI tree change listener leaks
a445e2c: table greyer (ability to disable a table)
dff15af: IDEA-105047 Map help button and F1 of the Breakpoints dialog
06fbfa3: WEB-11122 LiveConsole: do not hide input/output
e7ed9a2: cleanup use EditorUtil.scrollToTheEnd
2b22f1a: IDEA-121445 Incomplete breakpoint background highlighting
6cb7fe8: use SmartList
132c8d9: cleanup
34499ed: cleanup
9f501ce: Merge remote-tracking branch 'origin/master'
bbb835a: IDEA-121530 New Mac Messages: 'Invalidate caches' message (with 4 buttons) has one button cut off - First part. The message should be re-layouted. Currently, where is an empty space in the top right part of the message.
524e89e: fix AIOOBE
ee029e5: EA-33362 - assert: DocumentImpl.createRangeMarker
e2b452b: Merge remote-tracking branch 'origin/master'
551e0c5: fixed PY-12228 Project Interpreter: not possible to remove default-located interpreter from the list
df34787: IDEA-121533 INRE at com.intellij.util.indexing.FileBasedIndexImpl.a
a45e0df: EA-41231 (diagnostic)
1e94edc: Shadows improvement
cc01459: WEB-11194 runnerw.exe not working on win XP
10543d4: EA-54083, EA-54446 (premature disposal of default project prevented)
f455420: Merge remote-tracking branch 'origin/master'
0878209: Merging more than one newline in multi-line strings (PY-5532).
e3a7ad9: Implement 'Select all occurrences' action
3b82bfe: fixed PY-12211 Virtualenv interpreters associated with the current project are unsorted
e700d39: Merge remote-tracking branch 'origin/master'
7683348: updated after review.
25d38b4: fixed - toggle method breakpoint action added new breakpoint
d11a471: EA-52809 - IAE: GrClosureType.<init>
e8a5a73: EA-53171 Extracted a separate class for caching type definition stuff. Used CachedValueManager for caching class members, caches depends on its type definition changes and out_of_code_block_modification due to many synthetic members of a class get invalidated independently from its class.
287c82f: Removed TypeEvalContext parameter from PyType.isBuiltin()
466cbf4: EA-54177 - assert: Alarm._addRequest
168a1bc: show paths for detected sdk
eb3695f: new inference: non wildcard parametrization: reject primitive bounds
ab2348a: new inference: diamond in lambda return workaround
7fa42a6: java 1.8, stream api migration: temp disable for generics methods
6087cba: java 1.8, stream api migration: convert to method refs
fb65345: java 1.8, stream api migration: shorten class names
4e6b18e: switch on inplace scene builder
bae5e2a: IDEA-110943 apply patch: Do not add "-" at the end of new file - Part2
2544895: IDEA-121502 Breakpoint condition language is reverted to default once breakpoint properties opened
d96e7b4: do resolve symlinks in suggested python sdks
a52288b: IDEA-110943 apply patch: Do not add "-" at the end of new file
de93417: IDEA-121371 diff: change action caption
7805c3d: Merge remote-tracking branch 'origin/master'
e77d5bb: Switched to @NotNull call site in Callable.getCallType() and PyCallableType.getCallType()
9b235a9: updated after review.
eb0b14f: Changed Callable.getCallType() with explicit 'null' call site to Callable.getReturnType()
dd898e2: Introduced Callable.getCallType() instead of PyFunctionImpl.getReturnTypeWithoutCallSite()
112519d: Merge remote-tracking branch 'origin/master'
4f8a937: IDEA-73814 Scratchpad
257ba94: updated after review.
032ad71: Inlined getGenericReturnType()
888edb9: IDEA-121491 Breakpoints inside anonymous class used in a field initializer
9e9e8e5: Cache call site independent return types of callables in TypeEvalContext
513e07d: EA-54475
27ffe06: CR-IC-4596 (formatting)
f0d970f: use correct concurrency primitive
90c2460: notnull
4c29f54: javadoc
9b88e07: Merge remote-tracking branch 'origin/master'
a456069: diamonds are not available at this language level - testdata fixed
0cab1e2: java 1.8, stream api migration: collect (to be continued)
3f5e08e: do not throw exception
578ac0e: fix indents in testdata
3f111dc: EA-53845 fixed NPE. ProjectRootManager obviously cannot be obtained if delegate.getProject() == null. Some @NotNull & @Nullable added in relative places
2ff02a9: cleanup
f90ee78: Added Callable.getReturnType() and PyTypeProvider.getReturnType()
54786f4: Renamed PyTypeProvider.getReturnType() to getCallType()
ed026c0: Renamed Callable.getReturnType() to getCallType()
1f721bb: Added PyCallableType.getReturnType() for forthcoming return types caching
f65c546: myWatchedProjectCount should be nonnegative
3c66f51: introduced idea.no.system.path.space.monitoring property to skip checks for free space because it fails for yet unrecognized reasons (IDEA-118718)
2fb4a97: JavaFX Scene Builder integration
956b0e3: Exclude ui-designer-core from plugins
8339440: IDEA-121423 Groovy: don't add type arguments to text for reference generating since it can contain lexical errors. Add type arguments to generated reference instead.
fd724d2: IDEA-121082 Enter License dialog: cannot enter data if JetBrains Account fails or returns several licenses
1e5e753: IDEA-121359 License dialog: Undo not working in textfields
cb0399a: check for closure parameters: use method call conversion rules
914d6d4: Groovy: inference of closure parameter types: checks for explicitly declared types.
9446712: Duplicated error messages in @CompileStatic context fixed. Recoursive visitor is replaced with simple visitor, so we don't go inside child psi elements which can be inside @CompileStatic context
b7ba76c: Groovy: Support all ClosureSignatureHints
8951234: FromString hint: support correcr format. it describes a whole signature inside a single string.
22d33a0: ClosureSignatureHint works for closures with several parameters without declared types
d6f0faf: FromString hint: support options with a single String arg instead of an array of Strings
f30ccd9: Groovy: update mock groovy-2.3 build
258c222: Groovy: infrastructure for @ClosureParams support. FromString closure signature hint is supported
965c9b8: redundant code
17ad0ad: EA-53885 - CCE: GrIntroduceParameterProcessor.findUsages in-place introduce parameter is supported only for methods right now
d1b1b43: EA-54370 - IAE: GrIntroduceHandlerBase.getAnchor anchor should be @Nullable to get appropriate log message in case of null
d677a38: some null checks and cleanup
e5b4876: diff: DiffFragment.unchanged -> isEqual() == true
61b2c2a: diff: cleanup
b4a0790: Merge remote-tracking branch 'origin/master'
ac6700b: IDEA-121418 Update to EAP 134.1342 fails with access denied
41a88a4: diff: remove code duplication
45caaf6: diff: move HighlightingMode logic to TextCompareProcessor
ea4d527: EA-54427 - IAE: DiffUtil.getFramingColor
a30e0c6: Merge branch 'two-factor-auth'
49a7d1c: Merge branch 'diff-string'
eed23e9: diff: fix patience diff
442a1ad: Changes according to CR-IC-4570 (using VirtualFileWithId) and CR-IC-4490 (double checked locking)
01d1d11: A standalone EnforcedPlainTextFileTypeManagerTest
8207bd5: java: shorten references after refactoring
5cd9656: EA-54400 (getChildren() consistency guaranteed)
87f8b0f: search indexed files first, then elsewhere (not only whole-words, IDEA-121444)
d7e9631: search whole-words-only in indexed files first, then elsewhere (IDEA-121444)
9dab141: extract project scanning functionality to FindInProjectTask
7bc8adb: FindInProjectUtil cleanup & shortening
fbf5bbe: GeneralCommandLine: 'warn' level changed to 'info' level
7647e15: fix compilation under 1.8
e268b4d: EA-54442 - assert: ComponentManagerImpl.getComponent
c2bee64: restore error on diamonds under 1.6 (IDEA-121377)
0407c16: new inference: cleanup
d8b3e5c: new inference: captures should stay closed inside nested calls
e683dc8: new inference: wildcard parametrization for lambda with formal params: assignability check for complete parametrization only
cfcc34b: IDEA-121251 (stray annotation highlighted)
b8e291a: better tracing resource problem
32c5c60: correctly serialize multiline conditions and log messages
e78e195: do not save null in text and extra text
055191e: use chunk.getPresentableShortName in FormsInstrumenter
6a70bb8: regression: IDEA-121390 Breakpoints: mute on / off: breakpoint appearance updates only on focus change
f23249b: avoid type warning
0d528ac: use trove collections
3c4c139: IDEA-120290 Deprecated methods in import popup.
10ab0f9: don't enumerate all chunk members in compiler status messages
8e74f05: IDEA-121433 ('Auto-unboxing' inspection misses cases)
3a48f58: Merge remote-tracking branch 'origin/master'
1c9512a: Deployment based remote interpreters.
9cfc582: New plugin description
362d96b: New plugin description
a80e03c: New plugin description
7a68bd8: New plugin description
b3d6fcf: issue a clear compilation error when there's no groovy library
6fa1f58: IDEA-117325 Coloring of variable disappears when variable reassigned a value inside an if(){}
35040d4: IDEA-121253 Allow to edit/add contract annotation for library method at usage location
d5e833a: Merge remote-tracking branch 'origin/master'
a047666: new inference: non wildcard parametrization against the spec
ef581ff: restored method breakpoints notification
903d9cf: IDEA-121187 ("Method names differ only by case" is reported even if methods are different not only by case, but by signature as well)
59b0d0e: New plugin description
32e6a78: New plugin description
4da6bed: New plugin description
8f245e8: Merge branch 'python-fixes'
d99cf43: new "'ThreadLocalRandom' instance might be shared" inspection
728b702: improve description
b074b52: allow to set process handler
097ec87: Merge remote-tracking branch 'origin/master'
5ffd591: 'default charset for property files' option won't be ignored anymore
1234810: IDEA-120811 compile-server process hung with 0 CPU
a77644f: IDEA-117380 Can't remove multiple Maven projects at the same time
ff6b7d9: IDEA-121389 Breakpoint tooltip: duplicated information and red color
87346e3: Merge remote-tracking branch 'origin/master'
f26a54a: there is no template stuff in python community
e5552d8: fixed pycharm community detection
69cc1ef: remove GppCompilerTest
833bcfd: initialize LineSet before document changes
0ca5300: more tracing for myWatchedProjectsCount
99d35bf: IDEA-121393 Breakpoint: enabled breakpoint does not update its icon appearance
88b3931: License dialog: we don't need JBA availability check if actual license is JBA.
8fd9111: Fix for JToggleButton (we had no specific UI for Darcula/IntelliJ before)
f4ca614: Rename undo selection action
69b5912: Saving and loading of remote interpreters settings.
e7fd0b6: IDEA-121392 Breakpoint popup: click aside popup loses Suspend = Yes value
780a50b: IDEA-111432 Mnemonics changed for "Preserve case" and "Whole project"
a91ad4a: Don't require PsiFile.getText() for detecting Python charset declaration
3ca9628: remove ControlFlowUtils duplication
a1e2bb8: Remove unused ConditionalUtils
7b53c99: remove SideEffectChecker duplication
bcf9217: remove VariableAccessUtils duplication
a8412d2: plugin advertiser disabled for broken plugins (IDEA-121374)
2994241: Don't crawl down the tree for performance reasons, use cached globals
ba5925e: fixed ContextTest.testXDebugger test
0a6c9ae: test fixed
5690776: save memory on detected line separator
0b40c67: notnull
ed02fc9: optimisation
94f1638: javadoc
d37c7a9: EA-54432 - IAE: XDependentBreakpointManager.getMasterBreakpoint
df6f6f5: do not save empty condition and log message in breakpoints
a7c29b4: LanguageConsoleImpl calls createFile during initialization, so, inherited class cannot override it properly
cf066de: default methods: do not warn about protected methods from Object
5dd3ae6: Merge branch 'python-fixes'
229a0e9: CR-IC-4571 EditorExtensions.xml is overkill
018e061: WEB-4379 Smart step into does not give me all the methods
e79dc61: style
00e2508: IDEA-119238 Git and Hg Amend Commit: amend message updated for multi-root selection changes
e6d6bbb: Merge remote-tracking branch 'origin/master'
58d0444: IDEA-121383 Intellij EAP 1342 Does not start on Mac
39a393c: initialize default breakpoints for new project in tests
25e8977: prepare to fix WEB-4379 Smart step into does not give me all the methods, WEB-4440 Make debugger step inside the anonymous function of the $.each statement by default (or make it at least optional)
dda01ac: overrides, notnull
b6791ca: overrides
f1fef2c: correction to editor fixture to fix failing tests (IDEA-80056)
22985e2: load document LineSet lazily
13e43be: more debugging for GroovyCompilerTest
fdaed62: use IJ index-building classloader to speedup groovyc resolve when it's advantageous
80c7763: testdata fixed
e7cb908: new inference: method refs: apply reference rules first
cf7dff4: Support segue's
22a0e5f: compilation fix
e2c60e5: compilation fix
66a8ded: new inference: method refs: accept qualifier substitutor when nothing more could be inferred
e0f2061: select in project view: preserve registration order to prevent select in Packages by default
b31b23c: new inference: temp solution to exclude inference results from nested call of the same method on the outer level
5dd7e06: new inference: support for nested same method calls
fa6672f: new inference: simplify target type calculation
cbe62cc: new inference: guard fixed
a0f4efc: cleanup after batch folding operation end even in case of exception: to avoid observing invalid fold regions on subsequent batch folding operations
d63786d: allow non java xbreakpoints to be used in debugger-impl
600736c: preserve non java breakpoints in the BreakpointManager
bb586ed: java-xbreakpoints: do not save empty log message
bce82af: java-xbreakpoints: do not save empty conditions
1e9b8fb: java-xbreakpoints: rewrote breakpoints defaults
8541a5c: removed useless string conversion
2991835: java-xbreakpoints: support suspend policy defaults
d3a084dd: java-xbreakpoints: language selection support in condition and log expression
c7b3ad3: renamed attributes for exception breakpoint
b4df1c9: IDEA-121126 Debugger: mute breakpoints: Throwable at ApplicationImpl.assertReadAccessAllowed()
c388cfa: more clear breakpoint serialization format
3391b3b: fixed field and method breakpoints display name
d4f39df: java move to xbreakpoints: - cleanup after review
59b01e4: java move to xbreakpoints: - fixed old any exception breakpoint load
ca6bcc4: java move to xbreakpoints: - fixed breakpoint groupping
525d80d: java move to xbreakpoints 4: - fixed old breakpoints class deserialization
b903d10: java move to xbreakpoints 3: - breakpoint properties serialization fixes - import old java breakpoint - leave a copy for backward compatibility
d492412: java move to xbreakpoints 2: - cleanup - fixed tests - support run to cursor and smart step into - support add field/method breakpoint actions
7a3a6cf: java move to xbreakpoints: - removed java own breakpoints UI - added UI for java filters - added support for all kinds of java breakpoints
88189cc: New plugin description
17c097a: SlimEnterHandler should pass processing
f8d1847: New plugin description
2af38ae: new "Lambda parameter hides field" inspection
1f37c79: fix "Extract parameter as local variable" quickfix for expression lambda's
5fa2222: optimization for inspections tree filtering
a3bbf91: IDEA-105837 Intellij Idea caches maven snapshot dependencies forever
399fdef: fix multi-caret completion issues, make TypedHandlers supporting block selection work also with multiple carets (IDEA-80056)
a3258e2: IDEA-121283 Multiple Carets: Alt-J keyboard shortcut should be changed for Mac
13c7ba0: improve stub-psi-mismatch diagnostic: add language
140bfa4: test from jps modules extracted to separate modules to get rid of cyclic dependencies involving JPS modules
c367db2: 'Select in -> Project Structure' should select corresponding module when invoked on iml file
75feb75: EA-54419 (severity lowered)
93287e7: fixed PY-12248 Project Interpreters: redundant add virtualenv dialog on creating venv from project creation dialog
279985e: Faster isInBuilitins check that doesn't require resolve for non-builtin names
62df9b7: removed generate skeletons action
0cfaba5: New plugin description
2a39a63: IDEA-121285 Maven: missing classifier in managed dependency
16748dc: lazy icons for groovy elements
53ae56b: correct server log location in GroovyCompilerTest
13bfcb5: why does GroovyCompilerTest blink on TC?
5c2b079: IDEA-81276 Show the current program execution point does not bring hidden windows to front
9df88a0: overrides, notnull
4ecfba9: Merge remote-tracking branch 'origin/master'
eb1027b: fixed PY-12251 Project Interpreters: Create virtualenv from settings doesn't update warnigns about python package management tools
08190b2: IDEA-116029 in-place introduce variable name suggestions popup disappears before I can select anything
abf9500: Switched to potentially faster PyBuiltinCache.isInBuilins
7eebbf4: Fix for IDEA-121307 Cannot create new file (StubVirtualFile throws an exception on isDirectory)
daada4c: fixed PY-12257 IOOBE: CreateVirtualEnvDialog.setupDialog
2533839: do not duplicate existing sdks in create virtualenv
b649cb8b: Deprecated PyUtil.getConcealingParent
f16a6dd: Cleanup
ad552ed: CR-IC-4539
64d19ef: Moved isInBuiltins check for expressions to PyBuiltinCache
7113820: Github: do not provide Login/Password AuthData to Git on TwoFactor enabled
9194fc6: Renamed PyBuiltinCache.hasInBuiltins to isBuiltin
a4fef1b: LazyRangeMarkerFactory as project service — reapplied, add missed to RichPlatformPlugin.xml
82a44a6: Github: inspection warnings
92e93ca: Github: AtomicRef -> Ref
6a683af: Github: codereview
16d681e: Github: rewrite AuthDataHolder
741c46d: Github: do not rethrow exception twice
a33d7ef: Github: enable twofactor authorization
1f9c6da: EA-51130 (use data class' loader to register data flavor)
6f684e8: IDEA-121338 Multiple Carets: Menu items for multiple cursors are empty
50ad473: Revert: LazyRangeMarkerFactory as project service (b51fb7bf126a8c95ebf2223fb51c4b1d3faaa558)
e2b1588: ability to create OpenFileDescriptor using RangeMarker +review
d0ade84: LineColumnLazyMarker must compute delegate on start/end offset request +review
b51fb7b: LazyRangeMarkerFactory as project service +review
7cb4315: cleanup
104549e: update action presentations even if there are no mouse or key events
14e2cd6: fixed PY-12259 Assertion error on collecting Python installations on Mac
487e7c3: fixed PY-12261 Memory leak detected in python sdk details dialog
7e47f0e: UsefulTestCase.assertExists/assertDoesntExist for io.File
52ec148: platform: mute system notifications in tests and headless mode
5d41414: Switched from ArrayList to array for annotators for performance reasons
3174f1f: Merge remote-tracking branch 'origin/master'
340bdef: reverted nack template language selection to template language configurable (we don't have any template stuff in community edition)
ec14400: optimized icons
c741b28: Merge remote-tracking branch 'origin/master'
da79a3f: fixed PY-12267 Project Interpreters: inconsistent path separators for virtualenvs and base interpreters
abc49c3: added application root to the SDK search path on window (Education Edition attempt)
e1f5eb1: diff: do not create LineSeparator string every time
a7478db: diff: fix typo
41eed85: diff: rewrite DiffFragment
61dd3cd: diff: unify LineTokenizers
5ca37a6: diff: DiffString
c99c548: diff: fix patience diff
3717b9a: PY-12178 Support pull up / push down for properties (not ready yet: only properties excluded from other managers)
ad37f51: Merge remote-tracking branch 'origin/master'
eac76aa: fixed PY-12270 Project Interpreters: interpreter gets duplicated when hitting apply in multi-project settings window
094ac61: Merge remote-tracking branch 'origin/master'
5d4d015: Merge branch 'PY-10179' of https://github.com/Amarchuk/intellij-community into Amarchuk-PY-10179
be55f15: Merge remote-tracking branch 'origin/master'
68cfa2b: UI to create remote interpreter based on Vagrant.
150483d: fixed PY-12271 Project Interpreter: not able to set interpreter from Project Interpreters dialog when there are duplicated items in the list
40dd069: fixed PY-12272 Project Interpreter Setting Page: invalid alignment for multiproject list and packages table
3d19968: fix multi-line string with single quotes problem PY-12223
bf7f424: fix problem with single quote in project path http://youtrack.jetbrains.com/issue/PY-10179
Change-Id: I85e3d2231109799aab216989c887e0e48c87badb
diff --git a/python/helpers/pycharm_generator_utils/constants.py b/python/helpers/pycharm_generator_utils/constants.py
index 4ea8cf1..01079c4 100644
--- a/python/helpers/pycharm_generator_utils/constants.py
+++ b/python/helpers/pycharm_generator_utils/constants.py
@@ -6,7 +6,7 @@
import time
-VERSION = "1.133"
+VERSION = "1.135"
OUT_ENCODING = 'utf-8'
diff --git a/python/helpers/pycharm_generator_utils/module_redeclarator.py b/python/helpers/pycharm_generator_utils/module_redeclarator.py
index 8377879..dcae2b5 100644
--- a/python/helpers/pycharm_generator_utils/module_redeclarator.py
+++ b/python/helpers/pycharm_generator_utils/module_redeclarator.py
@@ -77,6 +77,7 @@
self.footer_buf = Buf(self)
self.indent_size = indent_size
self._indent_step = " " * self.indent_size
+ self.split_modules = False
#
self.imported_modules = {"": the_builtins} # explicit module imports: {"name": module}
self.hidden_imports = {} # {'real_mod_name': 'alias'}; we alias names with "__" since we don't want them exported
@@ -115,7 +116,7 @@
def flush(self):
init = None
try:
- if self.mod_filename and len(self.classes_buffs) >= 30:
+ if self.split_modules:
mod_path = self.outfile.strip(".py")
fname = build_output_name(mod_path, "__init__")
@@ -128,11 +129,9 @@
fname = build_output_name(mod_path, buf.name)
dummy = fopen(fname, "w")
self.header_buf.flush(dummy)
+ self.imports_buf.flush(dummy)
buf.flush(dummy)
- data += "from "
- if version[0] >= 3:
- data += "."
- data += buf.name + " import " + buf.name + "\n"
+ data += self.create_local_import(buf.name)
dummy.close()
init.write(data)
@@ -158,6 +157,13 @@
fake_builtin_init.__doc__ = object.__init__.__doc__ # this forces class's doc to be used instead
+ def create_local_import(self, name):
+ if len(name.split(".")) > 1: return ""
+ data = "from "
+ if version[0] >= 3:
+ data += "."
+ data += name + " import " + name + "\n"
+ return data
def find_imported_name(self, item):
"""
@@ -636,6 +642,11 @@
else:
bases_list.append(base_name)
base_def = "(" + ", ".join(bases_list) + ")"
+
+ for base in bases_list:
+ local_import = self.create_local_import(base)
+ if local_import:
+ out(indent, local_import)
out(indent, "class ", p_name, base_def, ":",
skipped_bases and " # skipped bases: " + ", ".join(skipped_bases) or "")
out_doc_attr(out, p_class, indent + 1)
@@ -968,6 +979,7 @@
ins_index = i # we could not go farther than current ins_index
break # ...and need not go fartehr than first known child
cls_list.insert(ins_index, (cls_name, get_mro(cls)))
+ self.split_modules = self.mod_filename and len(cls_list) >= 30
for item_name in [cls_item[0] for cls_item in cls_list]:
buf = ClassBuf(item_name, self)
self.classes_buffs.append(buf)
diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py
index f7bfb32..590687d 100644
--- a/python/helpers/pydev/pydevd.py
+++ b/python/helpers/pydev/pydevd.py
@@ -764,7 +764,7 @@
del self.exception_set[exception]
self.always_exception_set.remove(exception)
except:
- pass
+ pydev_log.debug("Error while removing exception"%sys.exc_info()[0]);
update_exception_hook(self)
elif cmd_id == CMD_LOAD_SOURCE:
diff --git a/python/helpers/pydev/pydevd_breakpoints.py b/python/helpers/pydev/pydevd_breakpoints.py
index 0a6644b..beebebf 100644
--- a/python/helpers/pydev/pydevd_breakpoints.py
+++ b/python/helpers/pydev/pydevd_breakpoints.py
@@ -127,6 +127,9 @@
debugger.force_post_mortem_stop += 1
pydevd_tracing.SetTrace(None) #no tracing from here
+
+ pydev_log.debug('Handling post-mortem stop on exception breakpoint %s'% exception_breakpoint.qname)
+
debugger.handle_post_mortem_stop(thread.additionalInfo, thread)
#=======================================================================================================================
diff --git a/python/helpers/pydev/pydevd_comm.py b/python/helpers/pydev/pydevd_comm.py
index 592a969..376065f 100644
--- a/python/helpers/pydev/pydevd_comm.py
+++ b/python/helpers/pydev/pydevd_comm.py
@@ -311,10 +311,12 @@
break
while buffer.find('\n') != -1:
command, buffer = buffer.split('\n', 1)
- pydev_log.debug('Received command: >>%s<<\n' % (command,))
+
args = command.split('\t', 2)
try:
- self.processCommand(int(args[0]), int(args[1]), args[2])
+ cmd_id = int(args[0])
+ pydev_log.debug('Received command: %s %s\n' % (ID_TO_MEANING.get(str(cmd_id), '???'), command,))
+ self.processCommand(cmd_id, int(args[1]), args[2])
except:
traceback.print_exc()
sys.stderr.write("Can't process net command: %s\n" % command)
@@ -383,7 +385,7 @@
out = cmd.getOutgoing()
if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1:
- out_message = 'sending cmd: '
+ out_message = 'Sending cmd: '
out_message += ID_TO_MEANING.get(out[:3], 'UNKNOWN')
out_message += ' '
out_message += out
diff --git a/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java b/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java
index b079014..ed2163a 100644
--- a/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java
+++ b/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java
@@ -25,9 +25,9 @@
import com.intellij.ui.ComboboxWithBrowseButton;
import com.intellij.util.NullableConsumer;
import com.intellij.util.containers.ContainerUtil;
-import com.jetbrains.python.configuration.PythonSdkDetailsDialog;
+import com.jetbrains.python.configuration.PyConfigurableInterpreterList;
import com.jetbrains.python.sdk.PyDetectedSdk;
-import com.jetbrains.python.sdk.PythonSdkType;
+import com.jetbrains.python.sdk.PythonSdkDetailsStep;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
import org.jetbrains.annotations.Nullable;
@@ -63,14 +63,7 @@
});
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- final List<Sdk> sdks = PythonSdkType.getAllSdks();
- PythonSdkDetailsDialog dialog = new PythonSdkDetailsDialog(project, new NullableConsumer<Sdk>() {
- @Override
- public void consume(@Nullable Sdk sdk) {
- comboBox.setModel(new CollectionComboBoxModel(sdks, sdk));
- }
- });
- dialog.show();
+ showOptions(project);
notifyChanged(e);
}
});
@@ -81,6 +74,19 @@
});
}
+ private void showOptions(final Project project) {
+ final PyConfigurableInterpreterList interpreterList = PyConfigurableInterpreterList.getInstance(project);
+ final Sdk[] sdks = interpreterList.getModel().getSdks();
+ PythonSdkDetailsStep.show(project, sdks, null, this, getButton().getLocationOnScreen(), new NullableConsumer<Sdk>() {
+ @Override
+ public void consume(@Nullable Sdk sdk) {
+ //noinspection unchecked
+ getComboBox().setModel(new CollectionComboBoxModel(interpreterList.getAllPythonSdks(), sdk));
+ }
+ }
+ );
+ }
+
private void notifyChanged(ActionEvent e) {
for (ActionListener changedListener : myChangedListeners) {
changedListener.actionPerformed(e);
diff --git a/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java b/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java
index 242d008..42dbef8 100644
--- a/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java
+++ b/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java
@@ -16,7 +16,6 @@
package com.jetbrains.python.configuration;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.ex.EditorEx;
@@ -26,6 +25,7 @@
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModel;
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
@@ -36,6 +36,9 @@
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.FixedSizeButton;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.CollectionComboBoxModel;
import com.intellij.util.NullableConsumer;
@@ -61,7 +64,7 @@
private final Project myProject;
@Nullable private final Module myModule;
private MySdkModelListener mySdkModelListener;
- private boolean myAddedSdk = false;
+ private List<Sdk> myAddedSdks = new ArrayList<Sdk>();
private PyConfigurableInterpreterList myInterpreterList;
private ProjectSdksModel myProjectSdksModel;
@@ -70,6 +73,7 @@
private JButton myDetailsButton;
private static final String SHOW_ALL = "Show All";
private NullableConsumer<Sdk> myDetailsCallback;
+ private PythonSdkDetailsDialog myMoreDialog;
public PyActiveSdkConfigurable(@NotNull Project project) {
myModule = null;
@@ -87,7 +91,6 @@
private void initContent() {
myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
- myInterpreterList.setSdkCombo(mySdkCombo);
myProjectSdksModel = myInterpreterList.getModel();
mySdkModelListener = new MySdkModelListener(this);
@@ -98,8 +101,7 @@
public void actionPerformed(ActionEvent e) {
final Sdk selectedSdk = (Sdk)mySdkCombo.getSelectedItem();
myPackagesPanel.updatePackages(selectedSdk != null ? new PyPackageManagementService(myProject, selectedSdk) : null);
- if (selectedSdk != null)
- myPackagesPanel.updateNotifications(selectedSdk);
+ myPackagesPanel.updateNotifications(selectedSdk);
}
});
myDetailsCallback = new NullableConsumer<Sdk>() {
@@ -110,7 +112,7 @@
final Sdk addedSdk = SdkConfigurationUtil.setupSdk(myProjectSdksModel.getSdks(), sdk.getHomeDirectory(),
PythonSdkType.getInstance(), true,
null, null);
- myAddedSdk = true;
+ myAddedSdks.add(addedSdk);
myProjectSdksModel.addSdk(addedSdk);
myProjectSdksModel.removeSdk(sdk);
mySdkCombo.setSelectedItem(addedSdk);
@@ -127,26 +129,28 @@
}
}
};
-
+ myMoreDialog = myModule == null ? new PythonSdkDetailsDialog(myProject, myDetailsCallback) :
+ new PythonSdkDetailsDialog(myModule, myDetailsCallback);
myDetailsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- PythonSdkDetailsStep
- .show(myProject, myProjectSdksModel.getSdks(),
- myModule == null ? new PythonSdkDetailsDialog(myProject, myDetailsCallback) :
- new PythonSdkDetailsDialog(myModule, myDetailsCallback), myMainPanel,
- myDetailsButton.getLocationOnScreen(), true,
+ PythonSdkDetailsStep.show(myProject, myProjectSdksModel.getSdks(),
+ myMoreDialog, myMainPanel,
+ myDetailsButton.getLocationOnScreen(),
new NullableConsumer<Sdk>() {
@Override
public void consume(Sdk sdk) {
if (sdk == null) return;
+ final PyRemovedSdkService sdkService = PyRemovedSdkService.getInstance();
+ sdkService.restoreSdk(sdk);
if (myProjectSdksModel.findSdk(sdk) == null) {
myProjectSdksModel.addSdk(sdk);
- myAddedSdk = true;
+ myAddedSdks.add(sdk);
}
updateSdkList(false);
mySdkCombo.getModel().setSelectedItem(sdk);
myPackagesPanel.updatePackages(new PyPackageManagementService(myProject, sdk));
+ myPackagesPanel.updateNotifications(sdk);
}
}
);
@@ -184,8 +188,7 @@
final PackagesNotificationPanel notificationsArea = new PackagesNotificationPanel(myProject);
final JComponent notificationsComponent = notificationsArea.getComponent();
final Dimension preferredSize = mySdkCombo.getPreferredSize();
- notificationsComponent.setPreferredSize(new Dimension(500, preferredSize.height));
-
+ notificationsArea.hide();
myDetailsButton = new FixedSizeButton();
myDetailsButton.setIcon(PythonIcons.Python.InterpreterGear);
//noinspection SuspiciousNameCombination
@@ -211,7 +214,7 @@
c.weightx = 0.0;
myMainPanel.add(myDetailsButton, c);
- c.insets = new Insets(2,2,2,2);
+ c.insets = new Insets(2,2,0,2);
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 3;
@@ -219,7 +222,7 @@
c.gridx = 0;
c.gridy = 2;
- c.weighty = 0.5;
+ c.weighty = 1.;
c.gridwidth = 3;
c.gridheight = GridBagConstraints.RELATIVE;
c.fill = GridBagConstraints.BOTH;
@@ -229,7 +232,7 @@
c.gridx = 0;
c.gridy = 3;
c.gridwidth = 3;
-
+ c.weighty = 0.;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.SOUTH;
@@ -245,7 +248,7 @@
public boolean isModified() {
final Sdk sdk = getSdk();
final Sdk selectedItem = (Sdk)mySdkCombo.getSelectedItem();
- return myAddedSdk || selectedItem instanceof PyDetectedSdk || sdk != myProjectSdksModel.findSdk(selectedItem);
+ return !myAddedSdks.isEmpty() || selectedItem instanceof PyDetectedSdk || sdk != myProjectSdksModel.findSdk(selectedItem);
}
@Nullable
@@ -260,18 +263,20 @@
@Override
public void apply() throws ConfigurationException {
final Sdk item = (Sdk)mySdkCombo.getSelectedItem();
+ Sdk newSdk = item;
if (item instanceof PyDetectedSdk) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
+ VirtualFile sdkHome = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
@Override
- public void run() {
- final Sdk sdk = SdkConfigurationUtil.createAndAddSDK(item.getName(), PythonSdkType.getInstance());
- myProjectSdksModel.removeSdk(item);
- myProjectSdksModel.addSdk(sdk);
- updateSdkList(true);
- mySdkCombo.setSelectedItem(sdk);
- setSdk(sdk);
+ public VirtualFile compute() {
+ return LocalFileSystem.getInstance().refreshAndFindFileByPath(item.getName());
}
- }, ModalityState.any());
+ });
+ newSdk = SdkConfigurationUtil.setupSdk(ProjectJdkTable.getInstance().getAllJdks(), sdkHome, PythonSdkType.getInstance(), true, null, null);
+ if (newSdk != null) {
+ myProjectSdksModel.addSdk(newSdk);
+ mySdkCombo.setSelectedItem(newSdk);
+ myProjectSdksModel.apply();
+ }
}
else {
final Sdk sdk = myProjectSdksModel.findSdk(item);
@@ -280,13 +285,13 @@
myProjectSdksModel.apply(null, true);
mySdkCombo.setSelectedItem(item);
}
- else if (myAddedSdk) {
- myProjectSdksModel.apply(null, true);
+ else if (!myAddedSdks.isEmpty()) {
+ myProjectSdksModel.apply();
}
}
final Sdk prevSdk = ProjectRootManager.getInstance(myProject).getProjectSdk();
- final Sdk selectedSdk = setSdk(item);
+ final Sdk selectedSdk = setSdk(newSdk);
// update string literals if different LanguageLevel was selected
if (prevSdk != null && selectedSdk != null) {
@@ -305,7 +310,7 @@
}
private Sdk setSdk(Sdk item) {
- myAddedSdk = false;
+ myAddedSdks.clear();
final Sdk selectedSdk = myProjectSdksModel.findSdk(item);
if (myModule == null) {
final ProjectRootManager rootManager = ProjectRootManager.getInstance(myProject);
@@ -342,8 +347,12 @@
@Override
public void reset() {
- myAddedSdk = false;
- myProjectSdksModel.reset(myProject);
+ if (!myAddedSdks.isEmpty()) {
+ for (Sdk sdk : myAddedSdks) {
+ myProjectSdksModel.removeSdk(sdk);
+ }
+ }
+ myAddedSdks.clear();
resetSdkList();
}
@@ -399,6 +408,7 @@
public void disposeUIResources() {
myProjectSdksModel.removeListener(mySdkModelListener);
myInterpreterList.disposeModel();
+ Disposer.dispose(myMoreDialog.getDisposable());
}
private static class MySdkModelListener implements SdkModel.Listener {
@@ -410,7 +420,15 @@
@Override
public void sdkAdded(Sdk sdk) {
+ final Object item = myConfigurable.mySdkCombo.getSelectedItem();
+
myConfigurable.resetSdkList();
+
+ if (item instanceof PyDetectedSdk) {
+ final String path = ((PyDetectedSdk)item).getHomePath();
+ if (path != null && path.equals(sdk.getHomePath()))
+ myConfigurable.mySdkCombo.setSelectedItem(sdk);
+ }
}
@Override
diff --git a/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java b/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java
index 87b9163..c7176dd 100644
--- a/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java
+++ b/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java
@@ -15,6 +15,8 @@
*/
package com.jetbrains.python.configuration;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
@@ -30,8 +32,10 @@
import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor;
import org.jetbrains.annotations.Nullable;
-import javax.swing.*;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
/**
* Manages the SDK model shared between PythonSdkConfigurable and PyActiveSdkConfigurable.
@@ -40,16 +44,6 @@
*/
public class PyConfigurableInterpreterList {
private ProjectSdksModel myModel;
- private JComboBox mySdkCombo;
-
- public void setSdkCombo(final JComboBox sdkCombo) {
- mySdkCombo = sdkCombo;
- }
-
- public void setSelectedSdk(final Sdk selectedSdk) {
- if (mySdkCombo != null)
- mySdkCombo.setSelectedItem(selectedSdk);
- }
public static PyConfigurableInterpreterList getInstance(Project project) {
return ServiceManager.getService(project, PyConfigurableInterpreterList.class);
@@ -89,42 +83,51 @@
final boolean isVEnv2 = PythonSdkType.isVirtualEnv(o2);
final boolean isRemote1 = PySdkUtil.isRemote(o1);
final boolean isRemote2 = PySdkUtil.isRemote(o2);
+
+ if (isVEnv1) {
+ if (project != null && associatedWithCurrent(o1, project)) {
+ if (associatedWithCurrent(o2, project)) return compareSdk(o1, o2);
+ return -1;
+ }
+ if (isVEnv2) {
+ return compareSdk(o1, o2);
+ }
+ return -1;
+ }
+ if (isVEnv2) return 1;
+ if (isRemote1) return 1;
+ if (isRemote2) return -1;
+
+ return compareSdk(o1, o2);
+ }
+
+ private int compareSdk(final Sdk o1, final Sdk o2) {
final PythonSdkFlavor flavor1 = PythonSdkFlavor.getFlavor(o1);
final PythonSdkFlavor flavor2 = PythonSdkFlavor.getFlavor(o2);
final LanguageLevel level1 = flavor1 != null ? flavor1.getLanguageLevel(o1) : LanguageLevel.getDefault();
final LanguageLevel level2 = flavor2 != null ? flavor2.getLanguageLevel(o2) : LanguageLevel.getDefault();
-
- if (isVEnv1) {
- if (project != null && associatedWithCurrent(o1, project)) return -1;
- if (isVEnv2) {
- final int compare = Comparing.compare(level1, level2);
- if (compare != 0) return -compare;
- return Comparing.compare(o1.getName(), o2.getName());
- }
- return -1;
- }
- if (isVEnv2) {
- return 1;
- }
- if (isRemote1) return 1;
- if (isRemote2) return -1;
-
final int compare = Comparing.compare(level1, level2);
if (compare != 0) return -compare;
return Comparing.compare(o1.getName(), o2.getName());
}
});
- final Collection<String> sdkHomes = new ArrayList<String>();
+ final List<String> sdkHomes = new ArrayList<String>();
sdkHomes.addAll(VirtualEnvSdkFlavor.INSTANCE.suggestHomePaths());
for (PythonSdkFlavor flavor : PythonSdkFlavor.getApplicableFlavors()) {
if (flavor instanceof VirtualEnvSdkFlavor) continue;
sdkHomes.addAll(flavor.suggestHomePaths());
}
-
+ Collections.sort(sdkHomes);
for (String sdkHome : SdkConfigurationUtil.filterExistingPaths(PythonSdkType.getInstance(), sdkHomes, getModel().getSdks())) {
result.add(new PyDetectedSdk(sdkHome));
}
+ Iterables.removeIf(result, new Predicate<Sdk>() {
+ @Override
+ public boolean apply(@Nullable Sdk input) {
+ return input != null && PyRemovedSdkService.getInstance().isRemoved(input);
+ }
+ });
return result;
}
diff --git a/python/ide/src/com/jetbrains/python/configuration/PyRemovedSdkService.java b/python/ide/src/com/jetbrains/python/configuration/PyRemovedSdkService.java
new file mode 100644
index 0000000..f0927f7
--- /dev/null
+++ b/python/ide/src/com/jetbrains/python/configuration/PyRemovedSdkService.java
@@ -0,0 +1,66 @@
+/*
+ * 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.configuration;
+
+import com.intellij.openapi.components.*;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@State(
+ name = "PyRemovedSdkService",
+ storages = {
+ @Storage(
+ file = StoragePathMacros.APP_CONFIG + "/removedInterpreters.xml"
+ )}
+)
+public class PyRemovedSdkService implements PersistentStateComponent<PyRemovedSdkService> {
+
+ public static PyRemovedSdkService getInstance() {
+ return ServiceManager.getService(PyRemovedSdkService.class);
+ }
+
+ public Set<String> REMOVED_SDKS = new HashSet<String>();
+
+ public void removeSdk(@NotNull final Sdk sdk) {
+ REMOVED_SDKS.add(sdk.getHomePath());
+ }
+
+ public void restoreSdk(@NotNull final Sdk sdk) {
+ final String homePath = sdk.getHomePath();
+ if (REMOVED_SDKS.contains(homePath)) {
+ REMOVED_SDKS.remove(homePath);
+ }
+ }
+
+ public boolean isRemoved(@NotNull final Sdk sdk) {
+ final String homePath = sdk.getHomePath();
+ return REMOVED_SDKS.contains(homePath);
+ }
+
+ @Override
+ public PyRemovedSdkService getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(PyRemovedSdkService state) {
+ XmlSerializerUtil.copyBean(state, this);
+ }
+}
diff --git a/python/ide/src/com/jetbrains/python/configuration/PythonContentEntriesConfigurable.java b/python/ide/src/com/jetbrains/python/configuration/PythonContentEntriesConfigurable.java
index f67260b..e573aac 100644
--- a/python/ide/src/com/jetbrains/python/configuration/PythonContentEntriesConfigurable.java
+++ b/python/ide/src/com/jetbrains/python/configuration/PythonContentEntriesConfigurable.java
@@ -22,9 +22,12 @@
import com.intellij.openapi.options.NonDefaultProjectConfigurable;
import com.intellij.openapi.options.OptionalConfigurable;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ui.configuration.PlatformContentEntriesConfigurable;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.PlatformUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
/**
* @author yole
@@ -50,6 +53,8 @@
@NotNull
@Override
protected Configurable createModuleConfigurable(Module module) {
+ if (PlatformUtils.isPyCharmCommunity())
+ return new PlatformContentEntriesConfigurable(module, JavaSourceRootType.SOURCE);
return new PyContentEntriesModuleConfigurable(module);
}
}
diff --git a/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java b/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java
index 162ee67..68146c0 100644
--- a/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java
+++ b/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java
@@ -18,11 +18,13 @@
import com.google.common.collect.Sets;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModel;
import com.intellij.openapi.projectRoots.SdkModificator;
@@ -34,7 +36,10 @@
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Comparing;
-import com.intellij.remotesdk.RemoteCredentials;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.remote.RemoteCredentials;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
import com.intellij.util.NullableConsumer;
@@ -43,7 +48,6 @@
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
import com.jetbrains.python.sdk.*;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
-import icons.PythonIcons;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -72,9 +76,10 @@
private boolean myShowOtherProjectVirtualenvs = true;
private final Module myModule;
private NullableConsumer<Sdk> myShowMoreCallback;
+ private SdkModel.Listener myListener;
public PythonSdkDetailsDialog(Project project, NullableConsumer<Sdk> showMoreCallback) {
- super(project);
+ super(project, true);
myModule = null;
setTitle("Project Interpreters");
@@ -86,6 +91,12 @@
updateOkButton();
}
+ @Override
+ protected void dispose() {
+ myProjectSdksModel.removeListener(myListener);
+ super.dispose();
+ }
+
public PythonSdkDetailsDialog(Module module, NullableConsumer<Sdk> showMoreCallback) {
super(module.getProject());
myModule = module;
@@ -130,8 +141,7 @@
}
})
.addExtraAction(new ToggleVirtualEnvFilterButton())
- .addExtraAction(new ShowPathButton())
- .addExtraAction(new GenerateSkeletonsButton());
+ .addExtraAction(new ShowPathButton());
decorator.setPreferredSize(new Dimension(600, 500));
myMainPanel = decorator.createPanel();
@@ -141,7 +151,7 @@
}
private void addListeners() {
- myProjectSdksModel.addListener(new SdkModel.Listener() {
+ myListener = new SdkModel.Listener() {
@Override
public void sdkAdded(Sdk sdk) {
}
@@ -158,7 +168,8 @@
@Override
public void sdkHomeSelected(Sdk sdk, String newSdkHome) {
}
- });
+ };
+ myProjectSdksModel.addListener(myListener);
mySdkList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
updateOkButton();
@@ -223,7 +234,6 @@
if (!myShowOtherProjectVirtualenvs) {
VirtualEnvProjectFilter.removeNotMatching(myProject, pythonSdks);
}
- Collections.sort(pythonSdks, new PreferredSdkComparator());
//noinspection unchecked
mySdkList.setModel(new CollectionListModel<Sdk>(pythonSdks));
@@ -247,17 +257,20 @@
private void addSdk(AnActionButton button) {
PythonSdkDetailsStep
- .show(myProject, myProjectSdksModel.getSdks(), this, myMainPanel, button.getPreferredPopupPoint().getScreenPoint(), false,
+ .show(myProject, myProjectSdksModel.getSdks(), null, myMainPanel, button.getPreferredPopupPoint().getScreenPoint(),
new NullableConsumer<Sdk>() {
@Override
public void consume(Sdk sdk) {
- addCreatedSdk(sdk, false);
+ addCreatedSdk(sdk, true);
}
});
}
private void addCreatedSdk(@Nullable final Sdk sdk, boolean newVirtualEnv) {
if (sdk != null) {
+ final PyRemovedSdkService sdkService = PyRemovedSdkService.getInstance();
+ sdkService.restoreSdk(sdk);
+
boolean isVirtualEnv = PythonSdkType.isVirtualEnv(sdk);
if (isVirtualEnv && !newVirtualEnv) {
AddVEnvOptionsDialog dialog = new AddVEnvOptionsDialog(myMainPanel);
@@ -366,13 +379,15 @@
}
private void removeSdk() {
- final Sdk current_sdk = getSelectedSdk();
- if (current_sdk != null) {
- myProjectSdksModel.removeSdk(current_sdk);
- if (myModificators.containsKey(current_sdk)) {
- SdkModificator modificator = myModificators.get(current_sdk);
+ final Sdk currentSdk = getSelectedSdk();
+ if (currentSdk != null) {
+ final PyRemovedSdkService sdkService = PyRemovedSdkService.getInstance();
+ sdkService.removeSdk(currentSdk);
+ myProjectSdksModel.removeSdk(currentSdk);
+ if (myModificators.containsKey(currentSdk)) {
+ SdkModificator modificator = myModificators.get(currentSdk);
myModifiedModificators.remove(modificator);
- myModificators.remove(current_sdk);
+ myModificators.remove(currentSdk);
}
refreshSdkList();
mySdkListChanged = true;
@@ -420,7 +435,7 @@
@Override
public boolean isEnabled() {
- return !(getSelectedSdk() instanceof PyDetectedSdk);
+ return getSelectedSdk() != null;
}
@Override
@@ -438,7 +453,17 @@
component.setPreferredSize(new Dimension(600, 400));
component.setBorder(IdeBorderFactory.createBorder(SideBorder.ALL));
dialog.setCenterPanel(component);
- final Sdk sdk = getSelectedSdk();
+ Sdk sdk = getSelectedSdk();
+ if (sdk instanceof PyDetectedSdk) {
+ final String sdkName = sdk.getName();
+ VirtualFile sdkHome = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
+ @Override
+ public VirtualFile compute() {
+ return LocalFileSystem.getInstance().refreshAndFindFileByPath(sdkName);
+ }
+ });
+ sdk = SdkConfigurationUtil.setupSdk(ProjectJdkTable.getInstance().getAllJdks(), sdkHome, PythonSdkType.getInstance(), true, null, null);
+ }
editor.reload(sdk != null ? sdk.getSdkModificator(): null);
dialog.setTitle("Interpreter Paths");
@@ -446,36 +471,4 @@
updateOkButton();
}
}
-
- private class GenerateSkeletonsButton extends AnActionButton implements DumbAware {
- public GenerateSkeletonsButton() {
- super("Generate skeletons for the selected interpreter", PythonIcons.Python.Skeleton);
- }
-
- @Override
- public boolean isEnabled() {
- return (getSelectedSdk() instanceof PyDetectedSdk);
- }
-
- @Override
- public void actionPerformed(AnActionEvent e) {
- final Sdk sdk = getSelectedSdk();
- if (sdk instanceof PyDetectedSdk) {
- try {
- myProjectSdksModel.apply();
- }
- catch (ConfigurationException ignored) {
- }
-
- final Sdk addedSdk = SdkConfigurationUtil.setupSdk(myProjectSdksModel.getSdks(), sdk.getHomeDirectory(),
- PythonSdkType.getInstance(), true,
- null, null);
- myProjectSdksModel.addSdk(addedSdk);
- myProjectSdksModel.removeSdk(sdk);
- refreshSdkList();
- mySdkList.setSelectedValue(addedSdk, true);
- updateOkButton();
- }
- }
- }
}
diff --git a/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectDialog.java b/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectDialog.java
index 8ee900a..fc63971 100644
--- a/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectDialog.java
+++ b/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectDialog.java
@@ -26,7 +26,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.DirectoryProjectGenerator;
import com.intellij.platform.NewDirectoryProjectDialog;
-import com.intellij.remotesdk.RemoteSdkCredentials;
+import com.intellij.remote.RemoteSdkCredentials;
import com.intellij.ui.ComboboxWithBrowseButton;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel;
diff --git a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaClassType.java b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaClassType.java
index 02176e3..a667bb6 100644
--- a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaClassType.java
+++ b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaClassType.java
@@ -89,7 +89,7 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return false; // TODO: JDK's types could be considered built-in.
}
@@ -104,7 +104,7 @@
@Nullable
@Override
- public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
+ public PyType getReturnType(@NotNull TypeEvalContext context) {
if (myDefinition) {
return new PyJavaClassType(myClass, false);
}
@@ -113,6 +113,12 @@
@Nullable
@Override
+ public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite) {
+ return getReturnType(context);
+ }
+
+ @Nullable
+ @Override
public List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
return null;
}
diff --git a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaMethodType.java b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaMethodType.java
index dbcc7e2..6f0fd48 100644
--- a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaMethodType.java
+++ b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaMethodType.java
@@ -52,12 +52,18 @@
@Nullable
@Override
- public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
+ public PyType getReturnType(@NotNull TypeEvalContext context) {
return PyJavaTypeProvider.asPyType(myMethod.getReturnType());
}
@Nullable
@Override
+ public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite) {
+ return getReturnType(context);
+ }
+
+ @Nullable
+ @Override
public List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
return null;
}
@@ -84,7 +90,7 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return false;
}
diff --git a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaPackageType.java b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaPackageType.java
index 2948f21..6f891c0 100644
--- a/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaPackageType.java
+++ b/python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaPackageType.java
@@ -31,7 +31,6 @@
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import com.jetbrains.python.psi.types.PyType;
-import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -96,7 +95,7 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return false;
}
diff --git a/python/psi-api/src/com/jetbrains/python/PythonFileType.java b/python/psi-api/src/com/jetbrains/python/PythonFileType.java
index d940be6..d3d78c5 100644
--- a/python/psi-api/src/com/jetbrains/python/PythonFileType.java
+++ b/python/psi-api/src/com/jetbrains/python/PythonFileType.java
@@ -16,11 +16,15 @@
package com.jetbrains.python;
import com.intellij.lang.Language;
+import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
import icons.PythonPsiApiIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,6 +45,7 @@
*/
public class PythonFileType extends LanguageFileType {
private static final Pattern ENCODING_PATTERN = Pattern.compile("coding[:=]\\s*([-\\w.]+)");
+ public static final int MAX_CHARSET_ENCODING_LINE = 2;
public static PythonFileType INSTANCE = new PythonFileType();
@@ -100,14 +105,28 @@
}
@Nullable
- public static String getCharsetFromEncodingDeclaration(String content) {
+ public static String getCharsetFromEncodingDeclaration(@NotNull PsiFile file) {
+ final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
+ final String content;
+ if (document != null && document.getLineCount() > MAX_CHARSET_ENCODING_LINE) {
+ final int offset = document.getLineEndOffset(MAX_CHARSET_ENCODING_LINE);
+ content = document.getText(TextRange.create(0, offset));
+ }
+ else {
+ content = file.getText();
+ }
+ return getCharsetFromEncodingDeclaration(content);
+ }
+
+ @Nullable
+ private static String getCharsetFromEncodingDeclaration(@Nullable String content) {
if (content == null || content.isEmpty()) {
return null;
}
try {
final BufferedReader reader = new BufferedReader(new StringReader(content));
try {
- for (int i = 0; i < 2; i++) {
+ for (int i = 0; i < MAX_CHARSET_ENCODING_LINE; i++) {
final String line = reader.readLine();
if (line == null) {
return null;
diff --git a/python/psi-api/src/com/jetbrains/python/psi/Callable.java b/python/psi-api/src/com/jetbrains/python/psi/Callable.java
index 23a5ef7..a31197e 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/Callable.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/Callable.java
@@ -20,6 +20,8 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Map;
+
/**
* Something that can be called, passed parameters to, and return something back.
@@ -34,10 +36,24 @@
PyParameterList getParameterList();
/**
- * @return the type of returned value.
+ * Returns the return type of the callable independent of a call site.
*/
@Nullable
- PyType getReturnType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite);
+ PyType getReturnType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key);
+
+ /**
+ * Returns the type of the call to the callable.
+ */
+ @Nullable
+ PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite);
+
+ /**
+ * Returns the type of the call to the callable where the call site is specified by the optional receiver and the arguments to parameters
+ * mapping.
+ */
+ @Nullable
+ PyType getCallType(@Nullable PyExpression receiver, @NotNull Map<PyExpression, PyNamedParameter> parameters,
+ @NotNull TypeEvalContext context);
/**
* @return a methods returns itself, non-method callables return null.
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java b/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java
index 5ba21bf..f89f25f 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java
@@ -20,6 +20,8 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Collection;
+
/**
* Represents an argument list of a function call.
*
@@ -27,6 +29,12 @@
*/
public interface PyArgumentList extends PyElement {
+ /**
+ * @return all argument list param expressions (keyword argument or nameless)
+ */
+ @NotNull
+ Collection<PyExpression> getArgumentExpressions();
+
@NotNull
PyExpression[] getArguments();
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java
index 657a54f..a988714 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java
@@ -32,6 +32,7 @@
import org.jetbrains.annotations.Nullable;
import java.util.List;
+import java.util.Map;
/**
* Represents a class declaration in source.
@@ -113,6 +114,13 @@
PyFunction[] getMethods();
/**
+ * Get class properties.
+ * @return Map [property_name] = [{@link com.jetbrains.python.psi.Property}]
+ */
+ @NotNull
+ Map<String, Property> getProperties();
+
+ /**
* Finds a method with given name.
* @param name what to look for
* @param inherited true: search in superclasses; false: only look for methods defined in this class.
diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java
index ff188f5..5707005 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java
@@ -39,7 +39,10 @@
PyType getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context);
@Nullable
- PyType getReturnType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context);
+ PyType getReturnType(@NotNull Callable callable, @NotNull TypeEvalContext context);
+
+ @Nullable
+ PyType getCallType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context);
@Nullable
PyType getContextManagerVariableType(PyClass contextManager, PyExpression withExpression, TypeEvalContext context);
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableType.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableType.java
index 43261dd..66fb827 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableType.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyCallableType.java
@@ -34,14 +34,19 @@
boolean isCallable();
/**
- * Returns the type which is the result of calling an instance of this type.
+ * Returns the return type of a function independent of a call site.
*
- * @return the call result type or null if invalid.
+ * For example, it may return a generic type.
* @param context
- * @param callSite
*/
@Nullable
- PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite);
+ PyType getReturnType(@NotNull TypeEvalContext context);
+
+ /**
+ * Returns the type which is the result of calling an instance of this type.
+ */
+ @Nullable
+ PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite);
/**
* Returns the list of parameter types.
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyType.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyType.java
index 0987610..67ba765 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/types/PyType.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyType.java
@@ -73,9 +73,8 @@
/**
* @return true if the type is a known built-in type.
- * @param context
*/
- boolean isBuiltin(TypeEvalContext context);
+ boolean isBuiltin();
void assertValid(String message);
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java
index 6330c4a..c27dc4b 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java
@@ -94,8 +94,14 @@
return null;
}
+ @Nullable
@Override
- public PyType getReturnType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context) {
+ public PyType getReturnType(@NotNull Callable callable, @NotNull TypeEvalContext context) {
+ return null;
+ }
+
+ @Override
+ public PyType getCallType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context) {
ReturnTypeDescriptor descriptor;
synchronized (myMethodToReturnTypeMap) {
descriptor = myMethodToReturnTypeMap.get(function.getName());
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java b/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java
index bc53ffd..f3c688b 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java
@@ -18,6 +18,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.jetbrains.python.psi.Callable;
import com.jetbrains.python.psi.PyTypedElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,12 +42,19 @@
@Nullable private final PsiFile myOrigin;
private final Map<PyTypedElement, PyType> myEvaluated = new HashMap<PyTypedElement, PyType>();
+ private final Map<Callable, PyType> myEvaluatedReturn = new HashMap<Callable, PyType>();
private final ThreadLocal<Set<PyTypedElement>> myEvaluating = new ThreadLocal<Set<PyTypedElement>>() {
@Override
protected Set<PyTypedElement> initialValue() {
return new HashSet<PyTypedElement>();
}
};
+ private final ThreadLocal<Set<Callable>> myEvaluatingReturn = new ThreadLocal<Set<Callable>>() {
+ @Override
+ protected Set<Callable> initialValue() {
+ return new HashSet<Callable>();
+ }
+ };
private TypeEvalContext(boolean allowDataFlow, boolean allowStubToAST, @Nullable PsiFile origin) {
myAllowDataFlow = allowDataFlow;
@@ -114,64 +122,93 @@
}
return this;
}
-
+
public void trace(String message, Object... args) {
if (myTrace != null) {
myTrace.add(myTraceIndent + String.format(message, args));
}
}
-
+
public void traceIndent() {
if (myTrace != null) {
myTraceIndent += " ";
}
}
-
+
public void traceUnindent() {
if (myTrace != null && myTraceIndent.length() >= 2) {
myTraceIndent = myTraceIndent.substring(0, myTraceIndent.length()-2);
}
}
-
+
public String printTrace() {
return StringUtil.join(myTrace, "\n");
}
-
+
public boolean tracing() {
return myTrace != null;
}
@Nullable
- public PyType getType(@NotNull PyTypedElement element) {
- synchronized (myEvaluated) {
- if (myEvaluated.containsKey(element)) {
- final PyType pyType = myEvaluated.get(element);
- if (pyType != null) {
- pyType.assertValid(element.toString());
- }
- return pyType;
- }
- }
+ public PyType getType(@NotNull final PyTypedElement element) {
final Set<PyTypedElement> evaluating = myEvaluating.get();
if (evaluating.contains(element)) {
return null;
}
evaluating.add(element);
try {
- PyType result = element.getType(this, Key.INSTANCE);
- if (result != null) {
- result.assertValid(element.toString());
- }
synchronized (myEvaluated) {
- myEvaluated.put(element, result);
+ if (myEvaluated.containsKey(element)) {
+ final PyType type = myEvaluated.get(element);
+ assertValid(type, element);
+ return type;
+ }
}
- return result;
+ final PyType type = element.getType(this, Key.INSTANCE);
+ assertValid(type, element);
+ synchronized (myEvaluated) {
+ myEvaluated.put(element, type);
+ }
+ return type;
}
finally {
evaluating.remove(element);
}
}
+ @Nullable
+ public PyType getReturnType(@NotNull final Callable callable) {
+ final Set<Callable> evaluating = myEvaluatingReturn.get();
+ if (evaluating.contains(callable)) {
+ return null;
+ }
+ evaluating.add(callable);
+ try {
+ synchronized (myEvaluatedReturn) {
+ if (myEvaluatedReturn.containsKey(callable)) {
+ final PyType type = myEvaluatedReturn.get(callable);
+ assertValid(type, callable);
+ return type;
+ }
+ }
+ final PyType type = callable.getReturnType(this, Key.INSTANCE);
+ assertValid(type, callable);
+ synchronized (myEvaluatedReturn) {
+ myEvaluatedReturn.put(callable, type);
+ }
+ return type;
+ }
+ finally {
+ evaluating.remove(callable);
+ }
+ }
+
+ private static void assertValid(@Nullable PyType result, @NotNull PyTypedElement element) {
+ if (result != null) {
+ result.assertValid(element.toString());
+ }
+ }
+
public boolean maySwitchToAST(@NotNull PsiElement element) {
return myAllowStubToAST || myOrigin == element.getContainingFile();
}
diff --git a/python/resources/icons/com/jetbrains/python/skeleton.png b/python/resources/icons/com/jetbrains/python/skeleton.png
deleted file mode 100644
index b77c54c..0000000
--- a/python/resources/icons/com/jetbrains/python/skeleton.png
+++ /dev/null
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/skeleton@2x.png b/python/resources/icons/com/jetbrains/python/skeleton@2x.png
deleted file mode 100644
index 313b024..0000000
--- a/python/resources/icons/com/jetbrains/python/skeleton@2x.png
+++ /dev/null
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/templateRoot.png b/python/resources/icons/com/jetbrains/python/templateRoot.png
index a736036..32d4880 100644
--- a/python/resources/icons/com/jetbrains/python/templateRoot.png
+++ b/python/resources/icons/com/jetbrains/python/templateRoot.png
Binary files differ
diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml
index e402912..35a7e0b 100644
--- a/python/src/META-INF/python-core.xml
+++ b/python/src/META-INF/python-core.xml
@@ -372,6 +372,8 @@
serviceImplementation="com.jetbrains.python.codeInsight.PyCodeInsightSettings"/>
<applicationService serviceInterface="com.jetbrains.python.testing.PyTestFrameworkService"
serviceImplementation="com.jetbrains.python.testing.PyTestFrameworkService"/>
+ <applicationService serviceInterface="com.jetbrains.python.configuration.PyRemovedSdkService"
+ serviceImplementation="com.jetbrains.python.configuration.PyRemovedSdkService"/>
<autoImportOptionsProvider instance="com.jetbrains.python.codeInsight.imports.PyAutoImportOptions"/>
<defaultLiveTemplatesProvider implementation="com.jetbrains.python.codeInsight.liveTemplates.PyDefaultLiveTemplatesProvider"/>
diff --git a/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java b/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java
index 1048e53..27207ab 100644
--- a/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java
+++ b/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java
@@ -67,7 +67,7 @@
@Nullable
@Override
- public PyType getReturnType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context) {
+ public PyType getCallType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context) {
if (isInsideNumPy(function)) {
final NumPyDocString docString = NumPyDocString.forFunction(function, callSite);
if (docString != null) {
diff --git a/python/src/com/jetbrains/pyqt/PyQtTypeProvider.java b/python/src/com/jetbrains/pyqt/PyQtTypeProvider.java
index d9d030c..a57a4a5 100644
--- a/python/src/com/jetbrains/pyqt/PyQtTypeProvider.java
+++ b/python/src/com/jetbrains/pyqt/PyQtTypeProvider.java
@@ -15,12 +15,11 @@
*/
package com.jetbrains.pyqt;
+import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.Callable;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
-import com.jetbrains.python.psi.PyQualifiedExpression;
-import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import com.jetbrains.python.psi.types.PyClassTypeImpl;
import com.jetbrains.python.psi.types.PyType;
@@ -37,8 +36,9 @@
private static final String ourQt4Signal = "pyqtSignal";
@Override
- public PyType getReturnType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context) {
- if (PyNames.INIT.equals(function.getName())) {
+ public PyType getReturnType(@NotNull Callable callable, @NotNull TypeEvalContext context) {
+ if (PyNames.INIT.equals(callable.getName()) && callable instanceof PyFunction) {
+ final PyFunction function = (PyFunction)callable;
final PyClass containingClass = function.getContainingClass();
if (containingClass != null && ourQt4Signal.equals(containingClass.getName())) {
final String classQName = containingClass.getQualifiedName();
diff --git a/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java b/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java
index f30febe..15b29c1 100644
--- a/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java
+++ b/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -82,8 +82,7 @@
if (caretOffset == chars.length() || chars.charAt(caretOffset) != ':') {
textToType += ':';
}
- EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, textToType, true);
- editor.getCaretModel().moveToOffset(offset + 1 + pname.length()); // right after param name
+ EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, textToType, true, 1 + pname.length()); // right after param name
return Result.STOP;
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyDictKeyNamesCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyDictKeyNamesCompletionContributor.java
index cc7817f..d7b1598 100644
--- a/python/src/com/jetbrains/python/codeInsight/completion/PyDictKeyNamesCompletionContributor.java
+++ b/python/src/com/jetbrains/python/codeInsight/completion/PyDictKeyNamesCompletionContributor.java
@@ -131,7 +131,7 @@
if ("dict".equals(name)) {
final TypeEvalContext context = TypeEvalContext.userInitiated(callee.getContainingFile());
final PyType type = context.getType(dictConstructor);
- if (type != null && type.isBuiltin(context)) {
+ if (type != null && type.isBuiltin()) {
final PyArgumentList list = dictConstructor.getArgumentList();
if (list == null) return;
final PyExpression[] argumentList = list.getArguments();
diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PyDictConstructorToLiteralFormIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PyDictConstructorToLiteralFormIntention.java
index 322a31b..8a72aa2 100644
--- a/python/src/com/jetbrains/python/codeInsight/intentions/PyDictConstructorToLiteralFormIntention.java
+++ b/python/src/com/jetbrains/python/codeInsight/intentions/PyDictConstructorToLiteralFormIntention.java
@@ -58,7 +58,7 @@
if (expression != null && expression.isCalleeText("dict")) {
final TypeEvalContext context = TypeEvalContext.codeAnalysis(file);
PyType type = context.getType(expression);
- if (type != null && type.isBuiltin(context)) {
+ if (type != null && type.isBuiltin()) {
PyExpression[] argumentList = expression.getArguments();
for (PyExpression argument : argumentList) {
if (!(argument instanceof PyKeywordArgument)) return false;
diff --git a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java
index 8783a7a..39222b0 100644
--- a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java
+++ b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java
@@ -225,7 +225,7 @@
statementBody.append(PyNames.PASS);
}
else {
- if (!PyNames.INIT.equals(baseFunction.getName()) && baseFunction.getReturnType(context, null) != PyNoneType.INSTANCE) {
+ if (!PyNames.INIT.equals(baseFunction.getName()) && context.getReturnType(baseFunction) != PyNoneType.INSTANCE) {
statementBody.append("return ");
}
if (baseClass.isNewStyleClass()) {
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java
index 9ffb86d..ad1d6a2 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java
@@ -89,13 +89,13 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return false;
}
@Nullable
@Override
- public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
+ public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite) {
if (myDefinitionLevel > 0) {
return new PyNamedTupleType(myClass, myDeclaration, myName, myFields, myDefinitionLevel-1);
}
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
index 9cdf4c3..d7678c2 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
@@ -120,7 +120,7 @@
@Nullable
@Override
- public PyType getReturnType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context) {
+ public PyType getCallType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context) {
final String qname = getQualifiedName(function, callSite);
if (qname != null) {
if (OPEN_FUNCTIONS.contains(qname) && callSite != null) {
diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java
index b900e28..6fa6529 100644
--- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsTypeProvider.java
@@ -42,11 +42,12 @@
return null;
}
+ @Nullable
@Override
- public PyType getReturnType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context) {
- final PyFunction functionSkeleton = PyUserSkeletonsUtil.getUserSkeleton(function);
- if (functionSkeleton != null) {
- return functionSkeleton.getReturnType(context, callSite);
+ public PyType getReturnType(@NotNull Callable callable, @NotNull TypeEvalContext context) {
+ final Callable callableSkeleton = PyUserSkeletonsUtil.getUserSkeleton(callable);
+ if (callableSkeleton != null) {
+ return context.getReturnType(callableSkeleton);
}
return null;
}
diff --git a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form
index b6a71ee..5aacd41 100644
--- a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form
+++ b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.configuration.PyIntegratedToolsConfigurable">
- <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="9" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="8" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="657" height="302"/>
@@ -24,12 +24,12 @@
</component>
<vspacer id="fc19e">
<constraints>
- <grid row="8" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ <grid row="7" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="728f8" binding="myErrorPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
- <grid row="7" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="6" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -52,7 +52,7 @@
<grid id="e7a5f" binding="myDocStringsPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="3" column="0" row-span="2" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="2" column="0" row-span="2" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -87,7 +87,7 @@
<grid id="9f040" binding="myRestPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="5" column="0" row-span="2" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="4" column="0" row-span="2" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -117,20 +117,6 @@
</component>
</children>
</grid>
- <component id="a95d2" class="javax.swing.JComboBox" binding="myTemplateLanguage">
- <constraints>
- <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- </component>
- <component id="36fa5" class="javax.swing.JLabel">
- <constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value="Template language:"/>
- </properties>
- </component>
</children>
</grid>
</form>
diff --git a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
index 63d88c8..838839f 100644
--- a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
+++ b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
@@ -54,7 +54,6 @@
import com.jetbrains.python.documentation.PyDocumentationSettings;
import com.jetbrains.python.packaging.*;
import com.jetbrains.python.sdk.PythonSdkType;
-import com.jetbrains.python.templateLanguages.TemplatesService;
import com.jetbrains.python.testing.PythonTestConfigurationsModel;
import com.jetbrains.python.testing.TestRunnerService;
import com.jetbrains.python.testing.VFSTestFrameworkListener;
@@ -63,7 +62,6 @@
import javax.swing.*;
import java.awt.*;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -85,9 +83,6 @@
private JCheckBox analyzeDoctest;
private JPanel myDocStringsPanel;
private JPanel myRestPanel;
- private JComboBox myTemplateLanguage;
- private TemplatesConfigurationsModel myTemplatesModel;
- private TemplatesService myTemplatesService;
public PyIntegratedToolsConfigurable(@NotNull Module module) {
myModule = module;
@@ -107,7 +102,6 @@
myDocStringsPanel.setBorder(IdeBorderFactory.createTitledBorder("Docstrings"));
myRestPanel.setBorder(IdeBorderFactory.createTitledBorder("reStructuredText"));
- myTemplatesService = TemplatesService.getInstance(module);
}
@NotNull
@@ -198,10 +192,6 @@
myModel = new PythonTestConfigurationsModel(configurations,
TestRunnerService.getInstance(myModule).getProjectConfiguration(), myModule);
- List<String> templateConfigurations = TemplatesService.getAllTemplateLanguages();
- myTemplatesModel = new TemplatesConfigurationsModel(templateConfigurations, myTemplatesService);
- //noinspection unchecked
- myTemplateLanguage.setModel(myTemplatesModel);
updateConfigurations();
initErrorValidation();
return myMainPanel;
@@ -231,9 +221,6 @@
if (!getRequirementsPath().equals(myRequirementsPathField.getText())) {
return true;
}
- if (myTemplateLanguage.getSelectedItem() != myTemplatesModel.getTemplateLanguage()) {
- return true;
- }
return false;
}
@@ -242,11 +229,6 @@
if (!Comparing.equal(myDocstringFormatComboBox.getSelectedItem(), myDocumentationSettings.myDocStringFormat)) {
DaemonCodeAnalyzer.getInstance(myProject).restart();
}
- if (myTemplateLanguage.getSelectedItem() != myTemplatesModel.getTemplateLanguage()) {
- myTemplatesModel.apply();
- reparseFiles(Arrays.asList("html", "xml", "js")); //TODO: get from file extensions
- }
-
if (analyzeDoctest.isSelected() != myDocumentationSettings.analyzeDoctest) {
final List<VirtualFile> files = Lists.newArrayList();
ProjectRootManager.getInstance(myProject).getFileIndex().iterateContent(new ContentIterator() {
@@ -315,9 +297,6 @@
txtIsRst.setSelected(ReSTService.getInstance(myModule).txtIsRst());
analyzeDoctest.setSelected(myDocumentationSettings.analyzeDoctest);
myRequirementsPathField.setText(getRequirementsPath());
- myTemplateLanguage.setSelectedItem(myTemplatesModel.getTemplateLanguage());
- myTemplatesModel.reset();
-
}
@Override
diff --git a/python/src/com/jetbrains/python/configuration/TemplatesConfigurationsModel.java b/python/src/com/jetbrains/python/configuration/TemplatesConfigurationsModel.java
deleted file mode 100644
index 0722b36..0000000
--- a/python/src/com/jetbrains/python/configuration/TemplatesConfigurationsModel.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.jetbrains.python.configuration;
-
-import com.intellij.ui.CollectionComboBoxModel;
-import com.jetbrains.python.templateLanguages.TemplatesService;
-
-import java.util.List;
-
-/**
- * User: catherine
- */
-public class TemplatesConfigurationsModel extends CollectionComboBoxModel {
- private String myTemplateLanguage;
- private final TemplatesService myTemplatesService;
-
- public TemplatesConfigurationsModel(final List items, TemplatesService templatesService) {
- super(items, templatesService.getTemplateLanguage());
- myTemplatesService = templatesService;
- myTemplateLanguage = myTemplatesService.getTemplateLanguage();
- }
-
- public void reset() {
- setSelectedItem(myTemplateLanguage);
- }
-
- public void apply() {
- myTemplateLanguage = (String)getSelectedItem();
- myTemplatesService.setTemplateLanguage(myTemplateLanguage);
- }
-
- public Object getTemplateLanguage() {
- return myTemplateLanguage;
- }
-}
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
index b4d8360..8ef4ec9 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
@@ -137,13 +137,15 @@
// multiline strings handling
if (myInMultilineStringState != null) {
- if (PyConsoleUtil.isDoubleQuoteMultilineStarts(line)) {
+ if (PyConsoleUtil.isDoubleQuoteMultilineStarts(line) || PyConsoleUtil.isSingleQuoteMultilineStarts(line)) {
myInMultilineStringState = null;
// restore language
console.setLanguage(PythonLanguage.getInstance());
console.setPrompt(PyConsoleUtil.ORDINARY_PROMPT);
- }
- else {
+ } else {
+ if(line.equals("\n")) {
+ myInputBuffer.append("\n");
+ }
return;
}
}
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
index 213f635..c3f89cd 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
@@ -54,8 +54,8 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.FileElement;
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.remotesdk.RemoteSshProcess;
+import com.intellij.remote.RemoteSdkCredentials;
+import com.intellij.remote.RemoteSshProcess;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IJSwingUtilities;
diff --git a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
index 9c610e7..728056c 100644
--- a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
+++ b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
@@ -221,7 +221,7 @@
final String path = Joiner.on(", ").join(Collections2.transform(pythonPath, new Function<String, String>() {
@Override
public String apply(String input) {
- return "'" + input.replace("\\", "\\\\") + "'";
+ return "'" + input.replace("\\", "\\\\").replace("'", "\\'") + "'";
}
}));
diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
index 312db25..0bae7af 100644
--- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
+++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
@@ -34,7 +34,7 @@
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
-import com.intellij.remotesdk.RemoteProcessHandlerBase;
+import com.intellij.remote.RemoteProcessHandlerBase;
import com.intellij.xdebugger.*;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
import com.intellij.xdebugger.breakpoints.XBreakpointHandler;
diff --git a/python/src/com/jetbrains/python/debugger/PySmartStepIntoHandler.java b/python/src/com/jetbrains/python/debugger/PySmartStepIntoHandler.java
index af8b69f..5b12170 100644
--- a/python/src/com/jetbrains/python/debugger/PySmartStepIntoHandler.java
+++ b/python/src/com/jetbrains/python/debugger/PySmartStepIntoHandler.java
@@ -49,6 +49,7 @@
myProcess = process;
}
+ @Override
@NotNull
public List<PySmartStepIntoVariant> computeSmartStepVariants(@NotNull XSourcePosition position) {
final Document document = FileDocumentManager.getInstance().getDocument(position.getFile());
@@ -57,6 +58,7 @@
final int line = position.getLine();
XDebuggerUtil.getInstance().iterateLine(mySession.getProject(), document, line, new Processor<PsiElement>() {
+ @Override
public boolean process(PsiElement psiElement) {
addVariants(document, line, psiElement, variants, visitedCalls);
return true;
@@ -67,10 +69,11 @@
}
@Override
- public void startStepInto(PySmartStepIntoVariant smartStepIntoVariant) {
+ public void startStepInto(@NotNull PySmartStepIntoVariant smartStepIntoVariant) {
myProcess.startSmartStepInto(smartStepIntoVariant.getFunctionName());
}
+ @Override
public String getPopupTitle(@NotNull XSourcePosition position) {
return PyBundle.message("debug.popup.title.step.into.function");
}
diff --git a/python/src/com/jetbrains/python/debugger/PyStackFrame.java b/python/src/com/jetbrains/python/debugger/PyStackFrame.java
index 1c72e8b..2c8727c 100644
--- a/python/src/com/jetbrains/python/debugger/PyStackFrame.java
+++ b/python/src/com/jetbrains/python/debugger/PyStackFrame.java
@@ -69,7 +69,7 @@
}
@Override
- public void customizePresentation(ColoredTextContainer component) {
+ public void customizePresentation(@NotNull ColoredTextContainer component) {
component.setIcon(AllIcons.Debugger.StackFrame);
if (myPosition == null) {
diff --git a/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java b/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java
index ad1fa2d..6934a37 100644
--- a/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java
+++ b/python/src/com/jetbrains/python/documentation/PyTypeModelBuilder.java
@@ -226,7 +226,7 @@
parameterModels.add(new ParamType(parameter.getName(), build(parameter.getType(myContext), true)));
}
}
- final PyType ret = type.getCallType(myContext, null);
+ final PyType ret = type.getReturnType(myContext);
final TypeModel returnType = build(ret, true);
return new FunctionType(returnType, parameterModels);
}
diff --git a/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java b/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java
index 78d9d65..82f2605 100644
--- a/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java
+++ b/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java
@@ -99,6 +99,6 @@
return false;
}
return (PyNames.FAKE_OLD_BASE.equals(containingClass.getName()) ||
- (PyNames.OBJECT.equals(containingClass.getName()) && PyBuiltinCache.getInstance(fun).hasInBuiltins(containingClass)));
+ (PyNames.OBJECT.equals(containingClass.getName()) && PyBuiltinCache.getInstance(fun).isBuiltin(containingClass)));
}
}
diff --git a/python/src/com/jetbrains/python/inspections/PyArgumentEqualDefaultInspection.java b/python/src/com/jetbrains/python/inspections/PyArgumentEqualDefaultInspection.java
index 6a06f87..9b8b089 100644
--- a/python/src/com/jetbrains/python/inspections/PyArgumentEqualDefaultInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyArgumentEqualDefaultInspection.java
@@ -84,7 +84,7 @@
private static boolean hasSpecialCasedDefaults(Callable callable, PsiElement anchor) {
final String name = callable.getName();
final PyBuiltinCache cache = PyBuiltinCache.getInstance(anchor);
- if ("getattr".equals(name) && cache.hasInBuiltins(callable)) {
+ if ("getattr".equals(name) && cache.isBuiltin(callable)) {
return true;
}
else if ("get".equals(name) || "pop".equals(name)) {
diff --git a/python/src/com/jetbrains/python/inspections/PyBroadExceptionInspection.java b/python/src/com/jetbrains/python/inspections/PyBroadExceptionInspection.java
index 2731f8d..4b0945d 100644
--- a/python/src/com/jetbrains/python/inspections/PyBroadExceptionInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyBroadExceptionInspection.java
@@ -54,7 +54,7 @@
public static boolean equalsException(@NotNull PyClass cls, @NotNull TypeEvalContext context) {
final PyType type = context.getType(cls);
- return ("Exception".equals(cls.getName()) || "BaseException".equals(cls.getName())) && type != null && type.isBuiltin(context);
+ return ("Exception".equals(cls.getName()) || "BaseException".equals(cls.getName())) && type != null && type.isBuiltin();
}
private static class Visitor extends PyInspectionVisitor {
diff --git a/python/src/com/jetbrains/python/inspections/PyByteLiteralInspection.java b/python/src/com/jetbrains/python/inspections/PyByteLiteralInspection.java
index 536074e..0b5c93c 100644
--- a/python/src/com/jetbrains/python/inspections/PyByteLiteralInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyByteLiteralInspection.java
@@ -75,7 +75,7 @@
);
}
- final String charsetString = PythonFileType.getCharsetFromEncodingDeclaration(file.getText());
+ final String charsetString = PythonFileType.getCharsetFromEncodingDeclaration(file);
try {
if (charsetString != null && !Charset.forName(charsetString).equals(Charset.forName("US-ASCII")))
default_bytes = false;
diff --git a/python/src/com/jetbrains/python/inspections/PyComparisonWithNoneInspection.java b/python/src/com/jetbrains/python/inspections/PyComparisonWithNoneInspection.java
index 3883cd0..ec31c00 100644
--- a/python/src/com/jetbrains/python/inspections/PyComparisonWithNoneInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyComparisonWithNoneInspection.java
@@ -64,7 +64,7 @@
PsiReference reference = node.getReference();
assert reference != null;
PsiElement result = reference.resolve();
- if (result == null || PyBuiltinCache.getInstance(node).hasInBuiltins(result)) {
+ if (result == null || PyBuiltinCache.getInstance(node).isBuiltin(result)) {
registerProblem(node, "Comparison with None performed with equality operators", new ComparisonWithNoneQuickFix());
}
}
diff --git a/python/src/com/jetbrains/python/inspections/PyInitNewSignatureInspection.java b/python/src/com/jetbrains/python/inspections/PyInitNewSignatureInspection.java
index 6ced1d1..694d7ad 100644
--- a/python/src/com/jetbrains/python/inspections/PyInitNewSignatureInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyInitNewSignatureInspection.java
@@ -57,7 +57,7 @@
if (! cls.isNewStyleClass()) return; // old-style classes don't know about __new__
PyFunction init_or_new = cls.findInitOrNew(false); // only local
final PyBuiltinCache builtins = PyBuiltinCache.getInstance(cls);
- if (init_or_new == null || builtins.hasInBuiltins(init_or_new.getContainingClass())) return; // nothing is overridden
+ if (init_or_new == null || builtins.isBuiltin(init_or_new.getContainingClass())) return; // nothing is overridden
String the_other_name = PyNames.NEW.equals(init_or_new.getName()) ? PyNames.INIT : PyNames.NEW;
PyFunction the_other = cls.findMethodByName(the_other_name, true);
if (the_other == null || builtins.getClass("object") == the_other.getContainingClass()) return;
diff --git a/python/src/com/jetbrains/python/inspections/PyMandatoryEncodingInspection.java b/python/src/com/jetbrains/python/inspections/PyMandatoryEncodingInspection.java
index 58e9704..d41cfbe 100644
--- a/python/src/com/jetbrains/python/inspections/PyMandatoryEncodingInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyMandatoryEncodingInspection.java
@@ -62,7 +62,7 @@
@Override
public void visitPyFile(PyFile node) {
- final String charsetString = PythonFileType.getCharsetFromEncodingDeclaration(node.getText());
+ final String charsetString = PythonFileType.getCharsetFromEncodingDeclaration(node);
if (charsetString == null) {
TextRange tr = new TextRange(0,0);
ProblemsHolder holder = getHolder();
diff --git a/python/src/com/jetbrains/python/inspections/PyMethodMayBeStaticInspection.java b/python/src/com/jetbrains/python/inspections/PyMethodMayBeStaticInspection.java
index 71f2772..acf33c5 100644
--- a/python/src/com/jetbrains/python/inspections/PyMethodMayBeStaticInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyMethodMayBeStaticInspection.java
@@ -32,8 +32,6 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Collection;
-
/**
* User: ktisha
*
@@ -66,10 +64,10 @@
final PyClass containingClass = node.getContainingClass();
if (containingClass == null) return;
if (PythonUnitTestUtil.isUnitTestCaseClass(containingClass)) return;
- final Collection<PsiElement> supers = PySuperMethodsSearch.search(node).findAll();
- if (!supers.isEmpty()) return;
- final Collection<PyFunction> overrides = PyOverridingMethodsSearch.search(node, true).findAll();
- if (!overrides.isEmpty()) return;
+ final PsiElement firstSuper = PySuperMethodsSearch.search(node).findFirst();
+ if (firstSuper != null) return;
+ final PyFunction firstOverride = PyOverridingMethodsSearch.search(node, true).findFirst();
+ if (firstOverride != null) return;
final PyDecoratorList decoratorList = node.getDecoratorList();
if (decoratorList != null) return;
if (node.getModifier() != null) return;
diff --git a/python/src/com/jetbrains/python/inspections/PyNonAsciiCharInspection.java b/python/src/com/jetbrains/python/inspections/PyNonAsciiCharInspection.java
index 3038b64..5fd0e56 100644
--- a/python/src/com/jetbrains/python/inspections/PyNonAsciiCharInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyNonAsciiCharInspection.java
@@ -69,7 +69,7 @@
if (LanguageLevel.forElement(node).isPy3K()) return;
PsiFile file = node.getContainingFile(); // can't cache this in the instance, alas
if (file == null) return;
- final String charsetString = PythonFileType.getCharsetFromEncodingDeclaration(file.getText());
+ final String charsetString = PythonFileType.getCharsetFromEncodingDeclaration(file);
boolean hasNonAscii = false;
diff --git a/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java b/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java
index f3fddba..1b3dfc6 100644
--- a/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java
@@ -24,7 +24,8 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.containers.hash.HashMap;
-import com.intellij.util.containers.hash.HashSet;
+import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
+import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
import com.jetbrains.python.psi.types.PyModuleType;
@@ -34,9 +35,7 @@
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.Collection;
import java.util.Map;
-import java.util.Set;
import java.util.regex.Pattern;
/**
@@ -71,17 +70,10 @@
public void visitPyAssignmentStatement(PyAssignmentStatement node) {
final PyFunction function = PsiTreeUtil.getParentOfType(node, PyFunction.class, true, PyClass.class);
if (function == null) return;
- final Collection<PyGlobalStatement> globalStatements = PsiTreeUtil.findChildrenOfType(function, PyGlobalStatement.class);
- final Set<String> globals = new HashSet<String>();
- for (PyGlobalStatement statement : globalStatements) {
- final PyTargetExpression[] statementGlobals = statement.getGlobals();
- for (PyTargetExpression global : statementGlobals) {
- globals.add(global.getName());
- }
- }
+ final Scope scope = ControlFlowCache.getScope(function);
for (PyExpression expression : node.getTargets()) {
final String name = expression.getName();
- if (name == null || globals.contains(name)) continue;
+ if (name == null || scope.isGlobal(name)) continue;
if (expression instanceof PyTargetExpression) {
final PyExpression qualifier = ((PyTargetExpression)expression).getQualifier();
if (qualifier != null) {
diff --git a/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java b/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java
index 967e6a4..27fff56 100644
--- a/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java
@@ -301,7 +301,9 @@
}
else {
PyReferenceExpression callSite = being_checked instanceof PyReferenceExpression ? (PyReferenceExpression) being_checked : null;
- hasReturns = !(callable.getReturnType(myTypeEvalContext, callSite) instanceof PyNoneType);
+ final PyType type = callSite != null ? callable.getCallType(myTypeEvalContext, callSite)
+ : myTypeEvalContext.getReturnType(callable);
+ hasReturns = !(type instanceof PyNoneType);
}
if (allowed ^ hasReturns) {
if (allowed && callable instanceof PyFunction) {
diff --git a/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java b/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java
index fe9ac7f..5277576 100644
--- a/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyProtectedMemberInspection.java
@@ -70,7 +70,10 @@
if (name != null && name.startsWith("_") && !name.startsWith("__") && !name.endsWith("__")) {
final PyClass parentClass = getClassOwner(node);
if (parentClass != null) {
- final PsiReference reference = node.getReference();
+ final PsiReference reference = node.getReference(resolveWithoutImplicits());
+ if (reference == null) {
+ return;
+ }
final PsiElement resolvedExpression = reference.resolve();
final PyClass resolvedClass = getClassOwner(resolvedExpression);
if (parentClass.isSubclass(resolvedClass))
diff --git a/python/src/com/jetbrains/python/inspections/PySetFunctionToLiteralInspection.java b/python/src/com/jetbrains/python/inspections/PySetFunctionToLiteralInspection.java
index f0bdeb3..e846fdb 100644
--- a/python/src/com/jetbrains/python/inspections/PySetFunctionToLiteralInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PySetFunctionToLiteralInspection.java
@@ -22,9 +22,7 @@
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
-import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
-import com.intellij.psi.PsiReference;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.inspections.quickfix.ReplaceFunctionWithSetLiteralQuickFix;
@@ -66,7 +64,7 @@
public void visitPyCallExpression(final PyCallExpression node) {
if (!isAvailable(node)) return;
PyExpression callee = node.getCallee();
- if (node.isCalleeText(PyNames.SET) && isInBuiltins(callee)) {
+ if (node.isCalleeText(PyNames.SET) && callee != null && PyBuiltinCache.isInBuiltins(callee)) {
PyExpression[] arguments = node.getArguments();
if (arguments.length == 1) {
PyElement[] elements = getSetCallArguments(node);
@@ -91,20 +89,6 @@
}
return LanguageLevel.forElement(node).supportsSetLiterals();
}
-
- private static boolean isInBuiltins(PyExpression callee) {
- if (callee instanceof PyQualifiedExpression && (((PyQualifiedExpression)callee).isQualified())) {
- return false;
- }
- PsiReference reference = callee.getReference();
- if (reference != null) {
- PsiElement resolved = reference.resolve();
- if (resolved != null && PyBuiltinCache.getInstance(callee).hasInBuiltins(resolved)) {
- return true;
- }
- }
- return false;
- }
}
public static PyElement[] getSetCallArguments(PyCallExpression node) {
diff --git a/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java b/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java
index 28ccafd..a72ec9e 100644
--- a/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java
@@ -111,7 +111,7 @@
// maybe the op is overridden and may produce side effects, like cout << "hello"
PyType type = myTypeEvalContext.getType(leftExpression);
if (type != null &&
- !type.isBuiltin(myTypeEvalContext) &&
+ !type.isBuiltin() &&
type.resolveMember(method, null, AccessDirection.READ, resolveWithoutImplicits()) != null) {
return true;
}
@@ -119,7 +119,7 @@
type = myTypeEvalContext.getType(rightExpression);
if (type != null) {
String rmethod = "__r" + method.substring(2); // __add__ -> __radd__
- if (!type.isBuiltin(myTypeEvalContext) && type.resolveMember(rmethod, null, AccessDirection.READ, resolveWithoutImplicits()) != null) {
+ if (!type.isBuiltin() && type.resolveMember(rmethod, null, AccessDirection.READ, resolveWithoutImplicits()) != null) {
return true;
}
}
diff --git a/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java b/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java
index 180fd1b..280822b 100644
--- a/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java
@@ -149,7 +149,7 @@
}
else if (rightExpression instanceof PyCallExpression) {
final Callable callable = ((PyCallExpression)rightExpression).resolveCalleeFunction(resolveContext);
- // TODO: Switch to Callable.getReturnType()
+ // TODO: Switch to Callable.getCallType()
if (callable instanceof PyFunction && myTypeEvalContext.maySwitchToAST((PyFunction) callable)) {
PyStatementList statementList = ((PyFunction)callable).getStatementList();
if (statementList == null) {
diff --git a/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java b/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
index 45df382..d31d19e 100644
--- a/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
@@ -102,7 +102,7 @@
}
final PyType argType = myTypeEvalContext.getType(entry.getKey());
if (!genericsCollected) {
- substitutions.putAll(PyTypeChecker.collectCallGenerics(results.getCallable(), results.getReceiver(), myTypeEvalContext));
+ substitutions.putAll(PyTypeChecker.unifyReceiver(results.getReceiver(), myTypeEvalContext));
genericsCollected = true;
}
checkTypes(paramType, argType, entry.getKey(), myTypeEvalContext, substitutions);
diff --git a/python/src/com/jetbrains/python/inspections/PyUnboundLocalVariableInspection.java b/python/src/com/jetbrains/python/inspections/PyUnboundLocalVariableInspection.java
index abec5b1..9e0031a 100644
--- a/python/src/com/jetbrains/python/inspections/PyUnboundLocalVariableInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyUnboundLocalVariableInspection.java
@@ -132,7 +132,7 @@
return;
}
final PsiElement resolved = ref.resolve();
- final boolean isBuiltin = PyBuiltinCache.getInstance(node).hasInBuiltins(resolved);
+ final boolean isBuiltin = PyBuiltinCache.getInstance(node).isBuiltin(resolved);
if (owner instanceof PyClass) {
if (isBuiltin || ScopeUtil.getDeclarationScopeOwner(owner, name) != null) {
return;
diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
index 9e08a47..2e33a1f 100644
--- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
@@ -749,7 +749,7 @@
PsiElement element = reference.getElement();
if (type instanceof PyClassTypeImpl) {
PyClass cls = ((PyClassType)type).getPyClass();
- if (!PyBuiltinCache.getInstance(element).hasInBuiltins(cls)) {
+ if (!PyBuiltinCache.getInstance(element).isBuiltin(cls)) {
if (element.getParent() instanceof PyCallExpression) {
actions.add(new AddMethodQuickFix(refText, (PyClassType)type, true));
}
@@ -886,7 +886,7 @@
return true;
}
method = resolveClassMember(cls, PyNames.GETATTRIBUTE, context);
- if (method != null && !PyBuiltinCache.getInstance(cls).hasInBuiltins(method)) {
+ if (method != null && !PyBuiltinCache.getInstance(cls).isBuiltin(method)) {
return true;
}
return false;
diff --git a/python/src/com/jetbrains/python/inspections/PyUnusedLocalInspectionVisitor.java b/python/src/com/jetbrains/python/inspections/PyUnusedLocalInspectionVisitor.java
index f788353..3dc4205 100644
--- a/python/src/com/jetbrains/python/inspections/PyUnusedLocalInspectionVisitor.java
+++ b/python/src/com/jetbrains/python/inspections/PyUnusedLocalInspectionVisitor.java
@@ -328,7 +328,7 @@
PyCallExpression expr = (PyCallExpression) source;
if (expr.isCalleeText("range", "xrange")) {
final Callable callee = expr.resolveCalleeFunction(PyResolveContext.noImplicits().withTypeEvalContext(myTypeEvalContext));
- if (callee != null && PyBuiltinCache.getInstance(forStatement).hasInBuiltins(callee)) {
+ if (callee != null && PyBuiltinCache.getInstance(forStatement).isBuiltin(callee)) {
return true;
}
}
diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java
index 82a5fd9..fe4ab8f 100644
--- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java
+++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java
@@ -49,8 +49,9 @@
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
-import com.intellij.remotesdk.RemoteFile;
-import com.intellij.remotesdk.RemoteSdkCredentials;
+import com.intellij.remote.RemoteSdkAdditionalData;
+import com.intellij.remote.RemoteFile;
+import com.intellij.remote.RemoteSdkCredentials;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.SystemProperties;
@@ -778,10 +779,17 @@
if (homePath == null) {
throw new PyExternalProcessException(ERROR_INVALID_SDK, helperPath, args, "Cannot find interpreter for SDK");
}
- if (sdkData instanceof RemoteSdkCredentials) { //remote interpreter
- final RemoteSdkCredentials remoteSdkCredentials = (RemoteSdkCredentials)sdkData;
+ if (sdkData instanceof RemoteSdkAdditionalData) { //remote interpreter
+ RemoteSdkCredentials remoteSdkCredentials;
+ try {
+ remoteSdkCredentials = ((RemoteSdkAdditionalData)sdkData).getRemoteSdkCredentials();
+ }
+ catch (InterruptedException e) {
+ LOG.error(e);
+ remoteSdkCredentials = null;
+ }
final PythonRemoteInterpreterManager manager = PythonRemoteInterpreterManager.getInstance();
- if (manager != null) {
+ if (manager != null && remoteSdkCredentials != null) {
final List<String> cmdline = new ArrayList<String>();
cmdline.add(homePath);
cmdline.add(RemoteFile.detectSystemByPath(homePath).createRemoteFile(helperPath).getPath());
diff --git a/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java b/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java
index d894786..0fdbc53 100644
--- a/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java
+++ b/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java
@@ -33,8 +33,8 @@
import com.jetbrains.python.sdk.flavors.IronPythonSdkFlavor;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import java.awt.*;
import java.util.List;
import java.util.Set;
@@ -51,8 +51,6 @@
public PyInstalledPackagesPanel(Project project, PackagesNotificationPanel area) {
super(project, area);
- setPreferredSize(new Dimension(500, 500));
-
myNotificationArea.addLinkHandler(INSTALL_SETUPTOOLS, new Runnable() {
@Override
public void run() {
@@ -78,7 +76,11 @@
return service != null ? service.getSdk() : null;
}
- public void updateNotifications(@NotNull final Sdk selectedSdk) {
+ public void updateNotifications(@Nullable final Sdk selectedSdk) {
+ if (selectedSdk == null) {
+ myNotificationArea.hide();
+ return;
+ }
final Application application = ApplicationManager.getApplication();
application.executeOnPooledThread(new Runnable() {
@Override
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index 83036ee..97b380b 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.java
@@ -857,7 +857,10 @@
*
* @param elt starting point of search.
* @return 'class' or 'def' element, or null if not found.
+ *
+ * @deprecated Use {@link ScopeUtil#getScopeOwner} instead.
*/
+ @Deprecated
@Nullable
public static PsiElement getConcealingParent(PsiElement elt) {
if (elt == null || elt instanceof PsiFile) {
@@ -1138,7 +1141,7 @@
if (reference == null) return false;
PsiElement resolved = reference.resolve();
PyBuiltinCache cache = PyBuiltinCache.getInstance(node);
- if (resolved != null && cache.hasInBuiltins(resolved)) {
+ if (resolved != null && cache.isBuiltin(resolved)) {
PyExpression[] args = node.getArguments();
if (args.length > 0) {
String firstArg = args[0].getText();
diff --git a/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java b/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java
index 692ff00..20e8c5d 100644
--- a/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/CallArgumentsMappingImpl.java
@@ -134,7 +134,7 @@
}
else {
PyType arg_type = context.getType(arg);
- if (arg_type != null && arg_type.isBuiltin(context) && "list".equals(arg_type.getName())) {
+ if (arg_type != null && arg_type.isBuiltin() && "list".equals(arg_type.getName())) {
mapped_args.add(arg); // we can't really analyze arbitrary lists statically yet
// but ListLiteralExpressions are handled by visitor
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
index dfe12ca..2e6120a 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
@@ -48,6 +48,23 @@
pyVisitor.visitPyArgumentList(this);
}
+ @Override
+ @NotNull
+ public Collection<PyExpression> getArgumentExpressions() {
+ final PyExpression[] arguments = getArguments();
+ final Collection<PyExpression> result = new ArrayList<PyExpression>(arguments.length);
+ for (final PyExpression expression : arguments) {
+ if (expression instanceof PyKeywordArgument) {
+ final PyExpression valueExpression = ((PyKeywordArgument)expression).getValueExpression();
+ result.add(valueExpression);
+ }
+ if (expression instanceof PyReferenceExpression) {
+ result.add(expression);
+ }
+ }
+ return result;
+ }
+
@NotNull
public PyExpression[] getArguments() {
return childrenToPsi(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), PyExpression.EMPTY_ARRAY);
diff --git a/python/src/com/jetbrains/python/psi/impl/PyBinaryExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyBinaryExpressionImpl.java
index bee876a..61513d1 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyBinaryExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyBinaryExpressionImpl.java
@@ -137,7 +137,7 @@
}
final PyTypeChecker.AnalyzeCallResults results = PyTypeChecker.analyzeCall(this, context);
if (results != null) {
- final PyType type = results.getCallable().getReturnType(context, this);
+ final PyType type = results.getCallable().getCallType(context, this);
if (!PyTypeChecker.isUnknown(type) && !(type instanceof PyNoneType)) {
return type;
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java
index b545290..0f4b081 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java
@@ -27,15 +27,9 @@
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiFileSystemItem;
-import com.intellij.psi.PsiManager;
+import com.intellij.psi.*;
import com.jetbrains.python.PyNames;
-import com.jetbrains.python.psi.LanguageLevel;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyFile;
-import com.jetbrains.python.psi.PySequenceExpression;
+import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PythonSdkPathCache;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.sdk.PythonSdkType;
@@ -183,7 +177,13 @@
@Nullable
public PsiElement getByName(@NonNls String name) {
if (myBuiltinsFile != null) {
- return myBuiltinsFile.getElementNamed(name);
+ final PsiElement element = myBuiltinsFile.getElementNamed(name);
+ if (element != null) {
+ return element;
+ }
+ }
+ if (myExceptionsFile != null) {
+ return myExceptionsFile.getElementNamed(name);
}
return null;
}
@@ -337,7 +337,7 @@
* @param target an element to check.
* @return true iff target is inside the __builtins__.py
*/
- public boolean hasInBuiltins(@Nullable PsiElement target) {
+ public boolean isBuiltin(@Nullable PsiElement target) {
if (target == null) return false;
if (! target.isValid()) return false;
final PsiFile the_file = target.getContainingFile();
@@ -347,4 +347,22 @@
// files are singletons, no need to compare URIs
return the_file == myBuiltinsFile || the_file == myExceptionsFile;
}
+
+ public static boolean isInBuiltins(@NotNull PyExpression expression) {
+ if (expression instanceof PyQualifiedExpression && (((PyQualifiedExpression)expression).isQualified())) {
+ return false;
+ }
+ final String name = expression.getName();
+ PsiReference reference = expression.getReference();
+ if (reference != null && name != null) {
+ final PyBuiltinCache cache = getInstance(expression);
+ if (cache.getByName(name) != null) {
+ final PsiElement resolved = reference.resolve();
+ if (resolved != null && cache.isBuiltin(resolved)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java
index 781dc28..45f0947 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java
@@ -198,7 +198,7 @@
final PyFunction function = (PyFunction)resolved;
final Property property = function.getProperty();
if (property != null && isQualifiedByInstance(function, qualifiers, context)) {
- final PyType type = function.getReturnType(context, null);
+ final PyType type = context.getReturnType(function);
if (type instanceof PyFunctionType) {
resolved = ((PyFunctionType)type).getCallable();
}
@@ -424,7 +424,7 @@
}
}
if (init != null) {
- final PyType t = init.getReturnType(context, (PyReferenceExpression)callee);
+ final PyType t = init.getCallType(context, (PyReferenceExpression)callee);
if (cls != null) {
if (init.getContainingClass() != cls) {
if (t instanceof PyCollectionType) {
@@ -439,7 +439,7 @@
}
if (cls != null && t == null) {
final PyFunction newMethod = cls.findMethodByName(PyNames.NEW, true);
- if (newMethod != null && !PyBuiltinCache.getInstance(call).hasInBuiltins(newMethod)) {
+ if (newMethod != null && !PyBuiltinCache.getInstance(call).isBuiltin(newMethod)) {
return PyUnionType.createWeakType(new PyClassTypeImpl(cls, false));
}
}
@@ -453,7 +453,7 @@
}
if (target instanceof Callable) {
final Callable callable = (Callable)target;
- return callable.getReturnType(context, (PyReferenceExpression)callee);
+ return callable.getCallType(context, (PyReferenceExpression)callee);
}
}
}
@@ -463,8 +463,14 @@
else {
final PyType type = context.getType(callee);
if (type instanceof PyCallableType) {
+ final PyCallableType callableType = (PyCallableType)type;
final PyQualifiedExpression callSite = callee instanceof PyQualifiedExpression ? (PyQualifiedExpression)callee : null;
- return ((PyCallableType) type).getCallType(context, callSite);
+ if (callSite != null) {
+ return callableType.getCallType(context, callSite);
+ }
+ else {
+ return callableType.getReturnType(context);
+ }
}
return null;
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
index bea0e10..eaa480b 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
@@ -381,6 +381,13 @@
}
@Override
+ @NotNull
+ public Map<String, Property> getProperties() {
+ initProperties();
+ return new HashMap<String, Property>(myPropertyCache);
+ }
+
+ @Override
public PyClass[] getNestedClasses() {
return getClassChildren(TokenSet.create(PyElementTypes.CLASS_DECLARATION), PyClass.ARRAY_FACTORY);
}
@@ -607,9 +614,7 @@
@Override
public Property findPropertyByCallable(Callable callable) {
- if (myPropertyCache == null) {
- myPropertyCache = initializePropertyCache();
- }
+ initProperties();
for (Property property : myPropertyCache.values()) {
if (property.getGetter().valueOrNull() == callable ||
property.getSetter().valueOrNull() == callable ||
@@ -621,10 +626,14 @@
}
private Property findLocalProperty(String name) {
+ initProperties();
+ return myPropertyCache.get(name);
+ }
+
+ private synchronized void initProperties() {
if (myPropertyCache == null) {
myPropertyCache = initializePropertyCache();
}
- return myPropertyCache.get(name);
}
private Map<String, Property> initializePropertyCache() {
@@ -750,7 +759,7 @@
if (!(callable instanceof StubBasedPsiElement) && !context.maySwitchToAST(callable)) {
return null;
}
- return callable.getReturnType(context, null);
+ return context.getReturnType(callable);
}
return null;
}
@@ -1149,7 +1158,7 @@
}
}
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(this);
- if (result.isEmpty() && isValid() && !builtinCache.hasInBuiltins(this)) {
+ if (result.isEmpty() && isValid() && !builtinCache.isBuiltin(this)) {
final String implicitSuperName = LanguageLevel.forElement(this).isPy3K() ? PyNames.OBJECT : PyNames.FAKE_OLD_BASE;
final PyClass implicitSuper = builtinCache.getClass(implicitSuperName);
if (implicitSuper != null) {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java
index 92e75ed..9e8ef1a 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyDecoratorImpl.java
@@ -65,7 +65,7 @@
if (node != null) {
PyReferenceExpression ref = (PyReferenceExpression)node.getPsi();
PsiElement target = ref.getReference().resolve();
- return PyBuiltinCache.getInstance(this).hasInBuiltins(target);
+ return PyBuiltinCache.getInstance(this).isBuiltin(target);
}
return false;
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
index 2ffc8e6..acc225b 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
@@ -15,7 +15,6 @@
*/
package com.jetbrains.python.psi.impl;
-import com.google.common.collect.Maps;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Pair;
@@ -176,42 +175,74 @@
@Nullable
@Override
- public PyType getReturnType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
- PyType type = getGenericReturnType(context, callSite);
- if (callSite == null) {
- return type;
+ public PyType getReturnType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) {
+ for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
+ final PyType returnType = typeProvider.getReturnType(this, context);
+ if (returnType != null) {
+ returnType.assertValid(typeProvider.toString());
+ return returnType;
+ }
+ }
+ if (context.maySwitchToAST(this) && LanguageLevel.forElement(this).isAtLeast(LanguageLevel.PYTHON30)) {
+ PyAnnotation anno = getAnnotation();
+ if (anno != null) {
+ PyClass pyClass = anno.resolveToClass();
+ if (pyClass != null) {
+ return new PyClassTypeImpl(pyClass, false);
+ }
+ }
+ }
+ final PyType docStringType = getReturnTypeFromDocString();
+ if (docStringType != null) {
+ docStringType.assertValid("from docstring");
+ return docStringType;
+ }
+ if (context.allowReturnTypes(this)) {
+ final Ref<? extends PyType> yieldTypeRef = getYieldStatementType(context);
+ if (yieldTypeRef != null) {
+ return yieldTypeRef.get();
+ }
+ return getReturnStatementType(context);
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite) {
+ PyType type = null;
+ for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
+ type = typeProvider.getCallType(this, callSite, context);
+ if (type != null) {
+ type.assertValid(typeProvider.toString());
+ break;
+ }
+ }
+ if (type == null) {
+ type = context.getReturnType(this);
}
final PyTypeChecker.AnalyzeCallResults results = PyTypeChecker.analyzeCallSite(callSite, context);
- if (PyTypeChecker.hasGenerics(type, context)) {
- if (results != null) {
- final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(this, results.getReceiver(), results.getArguments(),
- context);
- type = substitutions != null ? PyTypeChecker.substitute(type, substitutions, context) : null;
- }
- else {
- type = null;
- }
- }
if (results != null) {
- type = replaceSelf(type, results.getReceiver(), context);
- }
- if (results != null && isDynamicallyEvaluated(results.getArguments().values(), context)) {
- return PyUnionType.createWeakType(type);
+ return analyzeCallType(type, results.getReceiver(), results.getArguments(), context);
}
return type;
}
@Nullable
- /**
- * Suits when there is no call site(e.g. implicit __iter__ call in statement for)
- */
- public PyType getReturnTypeWithoutCallSite(@NotNull TypeEvalContext context,
- @Nullable PyExpression receiver) {
- PyType type = getGenericReturnType(context, null);
+ @Override
+ public PyType getCallType(@Nullable PyExpression receiver,
+ @NotNull Map<PyExpression, PyNamedParameter> parameters,
+ @NotNull TypeEvalContext context) {
+ return analyzeCallType(context.getReturnType(this), receiver, parameters, context);
+ }
+
+ @Nullable
+ private PyType analyzeCallType(@Nullable PyType type,
+ @Nullable PyExpression receiver,
+ @NotNull Map<PyExpression, PyNamedParameter> parameters,
+ @NotNull TypeEvalContext context) {
if (PyTypeChecker.hasGenerics(type, context)) {
- final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(this, receiver,
- Maps.<PyExpression, PyNamedParameter>newHashMap(),
- context);
+ final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(receiver, parameters, context);
if (substitutions != null) {
type = PyTypeChecker.substitute(type, substitutions, context);
}
@@ -219,7 +250,13 @@
type = null;
}
}
- return replaceSelf(type, receiver, context);
+ if (receiver != null) {
+ type = replaceSelf(type, receiver, context);
+ }
+ if (type != null && isDynamicallyEvaluated(parameters.values(), context)) {
+ type = PyUnionType.createWeakType(type);
+ }
+ return type;
}
@Nullable
@@ -250,39 +287,6 @@
}
@Nullable
- private PyType getGenericReturnType(@NotNull TypeEvalContext typeEvalContext, @Nullable PyQualifiedExpression callSite) {
- if (typeEvalContext.maySwitchToAST(this) && LanguageLevel.forElement(this).isAtLeast(LanguageLevel.PYTHON30)) {
- PyAnnotation anno = getAnnotation();
- if (anno != null) {
- PyClass pyClass = anno.resolveToClass();
- if (pyClass != null) {
- return new PyClassTypeImpl(pyClass, false);
- }
- }
- }
- for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
- final PyType returnType = typeProvider.getReturnType(this, callSite, typeEvalContext);
- if (returnType != null) {
- returnType.assertValid(typeProvider.toString());
- return returnType;
- }
- }
- final PyType docStringType = getReturnTypeFromDocString();
- if (docStringType != null) {
- docStringType.assertValid("from docstring");
- return docStringType;
- }
- if (typeEvalContext.allowReturnTypes(this)) {
- final Ref<? extends PyType> yieldTypeRef = getYieldStatementType(typeEvalContext);
- if (yieldTypeRef != null) {
- return yieldTypeRef.get();
- }
- return getReturnStatementType(typeEvalContext);
- }
- return null;
- }
-
- @Nullable
private Ref<? extends PyType> getYieldStatementType(@NotNull final TypeEvalContext context) {
Ref<PyType> elementType = null;
final PyBuiltinCache cache = PyBuiltinCache.getInstance(this);
@@ -386,8 +390,9 @@
return type;
}
}
+ final boolean hasCustomDecorators = PyUtil.hasCustomDecorators(this) && !PyUtil.isDecoratedAsAbstract(this) && getProperty() == null;
final PyFunctionType type = new PyFunctionType(this);
- if (getDecoratorList() != null) {
+ if (hasCustomDecorators) {
return PyUnionType.createWeakType(type);
}
return type;
diff --git a/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java
index 56249f1..0dd7591 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyLambdaExpressionImpl.java
@@ -27,6 +27,8 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Map;
+
/**
* @author yole
*/
@@ -61,10 +63,23 @@
@Nullable
@Override
- public PyType getReturnType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
+ public PyType getReturnType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) {
final PyExpression body = getBody();
- if (body != null) return context.getType(body);
- else return null;
+ return body != null ? context.getType(body) : null;
+ }
+
+ @Nullable
+ @Override
+ public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite) {
+ return context.getReturnType(this);
+ }
+
+ @Nullable
+ @Override
+ public PyType getCallType(@Nullable PyExpression receiver,
+ @NotNull Map<PyExpression, PyNamedParameter> parameters,
+ @NotNull TypeEvalContext context) {
+ return context.getReturnType(this);
}
@Nullable
diff --git a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java
index 6ad33d6..f38937d 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java
@@ -208,7 +208,7 @@
PyType initType = null;
final PyFunction init = containingClass.findInitOrNew(true);
if (init != null && init != func) {
- initType = init.getReturnType(context, null);
+ initType = context.getReturnType(init);
if (init.getContainingClass() != containingClass) {
if (initType instanceof PyCollectionType) {
final PyType elementType = ((PyCollectionType)initType).getElementType(context);
diff --git a/python/src/com/jetbrains/python/psi/impl/PyPrefixExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyPrefixExpressionImpl.java
index 71658f0..79535f2 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyPrefixExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyPrefixExpressionImpl.java
@@ -88,7 +88,7 @@
if (ref != null) {
final PsiElement resolved = ref.resolve();
if (resolved instanceof Callable) {
- return ((Callable)resolved).getReturnType(context, this);
+ return ((Callable)resolved).getCallType(context, this);
}
}
return null;
diff --git a/python/src/com/jetbrains/python/psi/impl/PySubscriptionExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PySubscriptionExpressionImpl.java
index 6143828..2b21e17 100644
--- a/python/src/com/jetbrains/python/psi/impl/PySubscriptionExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PySubscriptionExpressionImpl.java
@@ -71,7 +71,7 @@
if (ref != null) {
final PsiElement resolved = ref.resolve();
if (resolved instanceof Callable) {
- res = ((Callable)resolved).getReturnType(context, this);
+ res = ((Callable)resolved).getCallType(context, this);
}
}
if (PyTypeChecker.isUnknown(res) || res instanceof PyNoneType) {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java
index c56111e..060c39c 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java
@@ -54,6 +54,7 @@
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
@@ -243,8 +244,8 @@
if (exprType instanceof PyClassType) {
final PyClass cls = ((PyClassType)exprType).getPyClass();
final PyFunction enter = cls.findMethodByName(PyNames.ENTER, true);
- if (enter instanceof PyFunctionImpl) {
- final PyType enterType = ((PyFunctionImpl)enter).getReturnTypeWithoutCallSite(context, expression);
+ if (enter != null) {
+ final PyType enterType = enter.getCallType(expression, Collections.<PyExpression, PyNamedParameter>emptyMap(), context);
if (enterType != null) {
return enterType;
}
@@ -438,10 +439,7 @@
@Nullable
private static PyType getContextSensitiveType(@NotNull PyFunction function, @NotNull TypeEvalContext context,
@Nullable PyExpression source) {
- if (function instanceof PyFunctionImpl) {
- return ((PyFunctionImpl)function).getReturnTypeWithoutCallSite(context, source);
- }
- return function.getReturnType(context, null);
+ return function.getCallType(source, Collections.<PyExpression, PyNamedParameter>emptyMap(), context);
}
@Nullable
diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java
index e66a219..a537dae 100644
--- a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java
+++ b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java
@@ -212,7 +212,7 @@
PyExpression callee = ((PyCallExpression)qualifier).getCallee();
if (callee instanceof PyReferenceExpression && PyNames.SUPER.equals(callee.getName())) {
PsiElement target = ((PyReferenceExpression)callee).getReference().resolve();
- if (target != null && PyBuiltinCache.getInstance(qualifier).hasInBuiltins(target)) return false; // super() of unresolved type
+ if (target != null && PyBuiltinCache.getInstance(qualifier).isBuiltin(target)) return false; // super() of unresolved type
}
}
}
diff --git a/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java b/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java
index 3987e4e..bfa4024 100644
--- a/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java
+++ b/python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java
@@ -124,7 +124,7 @@
// special case hack to avoid the need of patching generator3.py
PyClass containingClass = callee.getContainingClass();
if (containingClass != null && PyNames.PROPERTY.equals(containingClass.getName()) &&
- PyBuiltinCache.getInstance(elementInCall).hasInBuiltins(containingClass)) {
+ PyBuiltinCache.getInstance(elementInCall).isBuiltin(containingClass)) {
return true;
}
diff --git a/python/src/com/jetbrains/python/psi/stubs/PyModuleNameIndex.java b/python/src/com/jetbrains/python/psi/stubs/PyModuleNameIndex.java
index 105aec5..f743b8e 100644
--- a/python/src/com/jetbrains/python/psi/stubs/PyModuleNameIndex.java
+++ b/python/src/com/jetbrains/python/psi/stubs/PyModuleNameIndex.java
@@ -70,11 +70,13 @@
return myDataIndexer;
}
+ @NotNull
@Override
public KeyDescriptor<String> getKeyDescriptor() {
return myKeyDescriptor;
}
+ @NotNull
@Override
public FileBasedIndex.InputFilter getInputFilter() {
return new DefaultFileTypeSpecificInputFilter(PythonFileType.INSTANCE);
diff --git a/python/src/com/jetbrains/python/psi/types/PyCallableTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyCallableTypeImpl.java
index f417f5a..dc63784 100644
--- a/python/src/com/jetbrains/python/psi/types/PyCallableTypeImpl.java
+++ b/python/src/com/jetbrains/python/psi/types/PyCallableTypeImpl.java
@@ -49,7 +49,13 @@
@Nullable
@Override
- public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
+ public PyType getReturnType(@NotNull TypeEvalContext context) {
+ return myReturnType;
+ }
+
+ @Nullable
+ @Override
+ public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite) {
return myReturnType;
}
@@ -105,7 +111,7 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return false;
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
index 715421a..778b838 100644
--- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
+++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
@@ -163,7 +163,7 @@
}
}
- if ("super".equals(getClassQName()) && isBuiltin(context) && location instanceof PyCallExpression) {
+ if ("super".equals(getClassQName()) && isBuiltin() && location instanceof PyCallExpression) {
// methods of super() call are not of class super!
PyExpression first_arg = ((PyCallExpression)location).getArgument(0, PyExpression.class);
if (first_arg != null) { // the usual case: first arg is the derived class that super() is proxying for
@@ -307,7 +307,7 @@
@Nullable
@Override
- public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
+ public PyType getReturnType(@NotNull TypeEvalContext context) {
if (isDefinition()) {
return new PyClassTypeImpl(getPyClass(), false);
}
@@ -316,6 +316,12 @@
@Nullable
@Override
+ public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite) {
+ return getReturnType(context);
+ }
+
+ @Nullable
+ @Override
public List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
return null;
}
@@ -530,8 +536,8 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
- return PyBuiltinCache.getInstance(myClass).hasInBuiltins(myClass);
+ public boolean isBuiltin() {
+ return PyBuiltinCache.getInstance(myClass).isBuiltin(myClass);
}
@Override
diff --git a/python/src/com/jetbrains/python/psi/types/PyFunctionType.java b/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
index 5e0c356..229fe26 100644
--- a/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
@@ -46,8 +46,14 @@
@Nullable
@Override
- public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
- return myCallable.getReturnType(context, callSite);
+ public PyType getReturnType(@NotNull TypeEvalContext context) {
+ return context.getReturnType(myCallable);
+ }
+
+ @Nullable
+ @Override
+ public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite) {
+ return myCallable.getCallType(context, callSite);
}
@Nullable
@@ -79,7 +85,7 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return false;
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyGenericType.java b/python/src/com/jetbrains/python/psi/types/PyGenericType.java
index af7aaae..68256ae 100644
--- a/python/src/com/jetbrains/python/psi/types/PyGenericType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyGenericType.java
@@ -59,7 +59,7 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return false;
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyImportedModuleType.java b/python/src/com/jetbrains/python/psi/types/PyImportedModuleType.java
index 3b56b63..5f66c81 100644
--- a/python/src/com/jetbrains/python/psi/types/PyImportedModuleType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyImportedModuleType.java
@@ -90,7 +90,7 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return false; // no module can be imported from builtins
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyModuleType.java b/python/src/com/jetbrains/python/psi/types/PyModuleType.java
index 5e495cd..f58f8f8 100644
--- a/python/src/com/jetbrains/python/psi/types/PyModuleType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyModuleType.java
@@ -407,7 +407,7 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return true;
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyNoneType.java b/python/src/com/jetbrains/python/psi/types/PyNoneType.java
index 05a7931..417f0ce 100644
--- a/python/src/com/jetbrains/python/psi/types/PyNoneType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyNoneType.java
@@ -53,7 +53,7 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return true;
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyTupleType.java b/python/src/com/jetbrains/python/psi/types/PyTupleType.java
index 8ede14e..ae6ca00 100644
--- a/python/src/com/jetbrains/python/psi/types/PyTupleType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyTupleType.java
@@ -63,7 +63,7 @@
}
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
return true;
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
index 632633b..cbdeb16 100644
--- a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
+++ b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java
@@ -20,7 +20,6 @@
import com.intellij.psi.PsiReference;
import com.intellij.psi.ResolveResult;
import com.jetbrains.python.PyNames;
-import com.jetbrains.python.codeInsight.stdlib.PyStdlibTypeProvider;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
@@ -172,8 +171,7 @@
}
}
}
- if (!match(expectedCallable.getCallType(context, null), actualCallable.getCallType(context, null), context, substitutions,
- recursive)) {
+ if (!match(expectedCallable.getReturnType(context), actualCallable.getReturnType(context), context, substitutions, recursive)) {
return false;
}
return true;
@@ -259,7 +257,7 @@
}
}
}
- collectGenerics(callable.getCallType(context, null), context, collected, visited);
+ collectGenerics(callable.getReturnType(context), context, collected, visited);
}
}
@@ -309,7 +307,7 @@
substParams.add(subst);
}
}
- final PyType substResult = substitute(callable.getCallType(context, null), substitutions, context);
+ final PyType substResult = substitute(callable.getReturnType(context), substitutions, context);
return new PyCallableTypeImpl(substParams, substResult);
}
}
@@ -317,11 +315,10 @@
}
@Nullable
- public static Map<PyGenericType, PyType> unifyGenericCall(@NotNull PyFunction function,
- @Nullable PyExpression receiver,
+ public static Map<PyGenericType, PyType> unifyGenericCall(@Nullable PyExpression receiver,
@NotNull Map<PyExpression, PyNamedParameter> arguments,
@NotNull TypeEvalContext context) {
- final Map<PyGenericType, PyType> substitutions = collectCallGenerics(function, receiver, context);
+ final Map<PyGenericType, PyType> substitutions = unifyReceiver(receiver, context);
for (Map.Entry<PyExpression, PyNamedParameter> entry : arguments.entrySet()) {
final PyNamedParameter p = entry.getValue();
if (p.isPositionalContainer() || p.isKeywordContainer()) {
@@ -337,8 +334,7 @@
}
@NotNull
- public static Map<PyGenericType, PyType> collectCallGenerics(@NotNull Callable callable, @Nullable PyExpression receiver,
- @NotNull TypeEvalContext context) {
+ public static Map<PyGenericType, PyType> unifyReceiver(@Nullable PyExpression receiver, @NotNull TypeEvalContext context) {
final Map<PyGenericType, PyType> substitutions = new LinkedHashMap<PyGenericType, PyType>();
// Collect generic params of object type
final Set<PyGenericType> generics = new LinkedHashSet<PyGenericType>();
@@ -347,14 +343,22 @@
for (PyGenericType t : generics) {
substitutions.put(t, t);
}
- final PyClass cls = (callable instanceof PyFunction) ? ((PyFunction)callable).getContainingClass() : null;
- if (cls != null) {
- final PyFunction init = cls.findInitOrNew(true);
- // Unify generics in constructor
- if (init != null) {
- final PyType initType = init.getReturnType(context, null);
- if (initType != null) {
- match(initType, qualifierType, context, substitutions);
+ // Unify generics in constructor
+ if (qualifierType != null) {
+ final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
+ // TODO: Resolve to __new__ as well
+ final List<? extends RatedResolveResult> results = qualifierType.resolveMember(PyNames.INIT, null, AccessDirection.READ,
+ resolveContext);
+ if (results != null && !results.isEmpty()) {
+ final PsiElement init = results.get(0).getElement();
+ if (init instanceof PyTypedElement) {
+ final PyType initType = context.getType((PyTypedElement)init);
+ if (initType instanceof PyCallableType) {
+ final PyType initReturnType = ((PyCallableType)initType).getReturnType(context);
+ if (initReturnType != null) {
+ match(initReturnType, qualifierType, context, substitutions);
+ }
+ }
}
}
}
diff --git a/python/src/com/jetbrains/python/psi/types/PyUnionType.java b/python/src/com/jetbrains/python/psi/types/PyUnionType.java
index abdc5ad..8572b72 100644
--- a/python/src/com/jetbrains/python/psi/types/PyUnionType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyUnionType.java
@@ -77,13 +77,12 @@
}
/**
- * @param context
* @return true if all types in the union are built-in.
*/
@Override
- public boolean isBuiltin(TypeEvalContext context) {
+ public boolean isBuiltin() {
for (PyType one : myMembers) {
- if (one == null || !one.isBuiltin(context)) return false;
+ if (one == null || !one.isBuiltin()) return false;
}
return true;
}
diff --git a/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureHandler.java b/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureHandler.java
index 719bc83..6895249 100644
--- a/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureHandler.java
@@ -153,7 +153,7 @@
final PyClass baseClass = deepestSuperMethod.getContainingClass();
final PyBuiltinCache cache = PyBuiltinCache.getInstance(baseClass);
String baseClassName = baseClass == null? "" : baseClass.getName();
- if (cache.hasInBuiltins(baseClass))
+ if (cache.isBuiltin(baseClass))
return function;
final String message = PyBundle.message(
"refactoring.change.signature.find.usages.of.base.class",
diff --git a/python/src/com/jetbrains/python/refactoring/classes/DependencyVisitor.java b/python/src/com/jetbrains/python/refactoring/classes/DependencyVisitor.java
index b22449d..6cb4504 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/DependencyVisitor.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/DependencyVisitor.java
@@ -38,9 +38,24 @@
}
final String calleeName = callee.getName();
- if ((calleeName != null) && calleeName.equals(myElementToFind.getName())) { // Check by name also
+ final String name = myElementToFind.getName();
+ if ((calleeName != null) && calleeName.equals(name)) { // Check by name also
myDependencyFound = true;
}
+
+ // Member could be used as method param
+ final PyArgumentList list = node.getArgumentList();
+ if (list != null) {
+ for (final PyExpression expression : node.getArgumentList().getArgumentExpressions()) {
+ final PsiReference reference = expression.getReference();
+ if ((reference != null) && reference.isReferenceTo(myElementToFind)) {
+ myDependencyFound = true;
+ }
+ if ((name != null) && name.equals(expression.getName())) {
+ myDependencyFound = true;
+ }
+ }
+ }
}
}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java
index 79f0382..25b8a23 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java
@@ -125,7 +125,7 @@
}
@NotNull
- public static List<PyFunction> copyMethods(Collection<PyFunction> methods, PyClass superClass) {
+ public static List<PyFunction> copyMethods(Collection<PyFunction> methods, PyClass superClass, boolean skipIfExist ) {
if (methods.isEmpty()) {
return Collections.emptyList();
}
@@ -133,7 +133,7 @@
rememberNamedReferences(e);
}
final PyFunction[] elements = methods.toArray(new PyFunction[methods.size()]);
- return addMethods(superClass, true, elements);
+ return addMethods(superClass, skipIfExist, elements);
}
/**
@@ -298,7 +298,7 @@
}
public static boolean insertImport(PsiElement anchor, PsiNamedElement element, @Nullable String asName, boolean preferFromImport) {
- if (PyBuiltinCache.getInstance(element).hasInBuiltins(element)) return false;
+ if (PyBuiltinCache.getInstance(element).isBuiltin(element)) return false;
final PsiFile newFile = element.getContainingFile();
final PsiFile file = anchor.getContainingFile();
if (newFile == file) return false;
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/ClassFieldsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/ClassFieldsManager.java
index 3bf4f00..281ad58 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/ClassFieldsManager.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/ClassFieldsManager.java
@@ -1,9 +1,9 @@
package com.jetbrains.python.refactoring.classes.membersManager;
-import com.jetbrains.python.psi.PyAssignmentStatement;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.psi.PyTargetExpression;
+import com.google.common.collect.FluentIterable;
+import com.jetbrains.NotNullPredicate;
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.psi.*;
import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
import org.jetbrains.annotations.NotNull;
@@ -31,8 +31,21 @@
protected Collection<PyElement> moveAssignments(@NotNull final PyClass from,
@NotNull final Collection<PyAssignmentStatement> statements,
@NotNull final PyClass... to) {
+ return moveAssignmentsImpl(from, statements, to);
+ }
+
+ /**
+ * Moves assignments from one class to anothers
+ * @param from source
+ * @param statements assignments
+ * @param to destination
+ * @return newly created assignments
+ */
+ static Collection<PyElement> moveAssignmentsImpl(@NotNull final PyClass from,
+ @NotNull final Collection<PyAssignmentStatement> statements,
+ @NotNull final PyClass... to) {
//TODO: Copy/paste with InstanceFieldsManager. Move to parent?
- final List<PyElement> result = new ArrayList<PyElement>();
+ final Collection<PyElement> result = new ArrayList<PyElement>();
for (final PyClass destClass : to) {
result.addAll(PyClassRefactoringUtil.copyFieldDeclarationToStatement(statements, destClass.getStatementList(), destClass));
}
@@ -49,6 +62,39 @@
@NotNull
@Override
protected List<PyTargetExpression> getFieldsByClass(@NotNull final PyClass pyClass) {
- return pyClass.getClassAttributes();
+ return FluentIterable.from(pyClass.getClassAttributes()).filter(new NoMetaAndProperties(pyClass)).toList();
+ }
+
+ /**
+ * Exclude "__metaclass__" field and properties (there should be separate managers for them)
+ * TODO: Check type and filter out any builtin element instead?
+ */
+ private static class NoMetaAndProperties extends NotNullPredicate<PyTargetExpression> {
+ @NotNull
+ private final PyClass myClass;
+
+ private NoMetaAndProperties(@NotNull final PyClass aClass) {
+ myClass = aClass;
+ }
+
+ @Override
+ public boolean applyNotNull(@NotNull final PyTargetExpression input) {
+ final String name = input.getName();
+ if (name == null) {
+ return false;
+ }
+ if (name.equals(PyNames.DUNDER_METACLASS)) {
+ return false;
+ }
+
+ final PyExpression assignedValue = input.findAssignedValue();
+ if (assignedValue instanceof PyCallExpression) {
+ final PyExpression callee = ((PyCallExpression)assignedValue).getCallee();
+ if ((callee != null) && PyNames.PROPERTY.equals(callee.getName()) && (myClass.findProperty(name, false) != null)) {
+ return false;
+ }
+ }
+ return true;
+ }
}
}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/FieldsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/FieldsManager.java
index cb15b2b..5dd3288 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/FieldsManager.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/FieldsManager.java
@@ -43,9 +43,9 @@
@NotNull
@Override
protected MultiMap<PyClass, PyElement> getDependencies(@NotNull final PyElement member) {
- final MultiMap<PyClass, PyElement> result = new MultiMap<PyClass, PyElement>();
- member.accept(new MyPyRecursiveElementVisitor(result));
- return result;
+ final PyRecursiveElementVisitorWithResult visitor = new MyPyRecursiveElementVisitor();
+ member.accept(visitor);
+ return visitor.myResult;
}
@Override
@@ -89,7 +89,7 @@
* @return list of fields in target expression (declaration) form
*/
@NotNull
- protected abstract List<PyTargetExpression> getFieldsByClass(@NotNull PyClass pyClass);
+ protected abstract Collection<PyTargetExpression> getFieldsByClass(@NotNull PyClass pyClass);
@NotNull
@@ -135,13 +135,7 @@
/**
* Fetches field declarations
*/
- private static class MyPyRecursiveElementVisitor extends PyRecursiveElementVisitor {
- @NotNull
- private final MultiMap<PyClass, PyElement> myResult;
-
- private MyPyRecursiveElementVisitor(@NotNull final MultiMap<PyClass, PyElement> result) {
- myResult = result;
- }
+ private static class MyPyRecursiveElementVisitor extends PyRecursiveElementVisitorWithResult {
@Override
public void visitPyReferenceExpression(final PyReferenceExpression node) {
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/InstanceFieldsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/InstanceFieldsManager.java
index a1e19c4..357d9e8 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/InstanceFieldsManager.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/InstanceFieldsManager.java
@@ -8,7 +8,6 @@
import com.jetbrains.python.psi.impl.PyFunctionBuilder;
import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
@@ -18,6 +17,7 @@
* @author Ilya.Kazakevich
*/
class InstanceFieldsManager extends FieldsManager {
+ private static final FieldsOnly FIELDS_ONLY = new FieldsOnly();
// PY-12170
@@ -92,8 +92,8 @@
@NotNull
@Override
- protected List<PyTargetExpression> getFieldsByClass(@NotNull final PyClass pyClass) {
- return pyClass.getInstanceAttributes();
+ protected Collection<PyTargetExpression> getFieldsByClass(@NotNull final PyClass pyClass) {
+ return Collections2.filter(pyClass.getInstanceAttributes(), FIELDS_ONLY);
}
private static class InitsOnly extends NotNullPredicate<PyAssignmentStatement> {
@@ -115,4 +115,11 @@
return myInitMethod.equals(functionWhereDeclared);
}
}
+
+ private static class FieldsOnly extends NotNullPredicate<PyTargetExpression> {
+ @Override
+ protected boolean applyNotNull(@NotNull final PyTargetExpression input) {
+ return input.getReference().resolve() instanceof PyTargetExpression;
+ }
+ }
}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java
index 437b808..b2d8dac 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java
@@ -20,7 +20,6 @@
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiNamedElement;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.MultiMap;
import com.jetbrains.NotNullPredicate;
@@ -45,7 +44,11 @@
* List of managers. Class delegates all logic to them.
*/
private static final Collection<? extends MembersManager<? extends PyElement>> MANAGERS =
- Arrays.asList(new MethodsManager(), new SuperClassesManager(), new ClassFieldsManager(), new InstanceFieldsManager());
+ Arrays.asList(new MethodsManager(),
+ new SuperClassesManager(),
+ new ClassFieldsManager(),
+ new InstanceFieldsManager(),
+ new PropertiesManager());
@NotNull
private final Class<T> myExpectedClass;
@@ -84,7 +87,7 @@
@SuppressWarnings({"unchecked", "rawtypes"}) //We check type at runtime
private static Collection<PyMemberInfo<PyElement>> transformSafely(@NotNull final PyClass pyClass,
@NotNull final MembersManager<?> manager) {
- final List<PyElement> membersCouldBeMoved = manager.getMembersCouldBeMoved(pyClass);
+ final List<? extends PyElement> membersCouldBeMoved = manager.getMembersCouldBeMoved(pyClass);
manager.checkElementTypes((Iterable)membersCouldBeMoved);
return (Collection<PyMemberInfo<PyElement>>)Collections2.transform(membersCouldBeMoved, (Function)manager);
}
@@ -175,7 +178,8 @@
/**
* Finds member in class.
- * @param pyClass class to find member in
+ *
+ * @param pyClass class to find member in
* @param pyElement element to find
* @return member info with element
*/
@@ -195,25 +199,10 @@
* @return list of members
*/
@NotNull
- protected abstract List<PyElement> getMembersCouldBeMoved(@NotNull PyClass pyClass);
+ protected abstract List<? extends PyElement> getMembersCouldBeMoved(@NotNull PyClass pyClass);
/**
- * Filters out named elements (ones that subclasses {@link com.intellij.psi.PsiNamedElement}) and {@link com.jetbrains.python.psi.PyElement})
- * that are null or has null name.
- * You need it sometimes when code has errors (i.e. bad formatted code with annotation may treat annotation as method with null name.
- * note: we should probably throw exceptions in such cases and display "refactoring not available" window in handler)
- *
- * @param elementsToFilter collection of elements to filter
- * @param <T> element type
- * @return collection of T with out of nulls and elemens whos {@link com.intellij.psi.PsiNamedElement#getName()} returns null
- */
- @NotNull
- protected static <T extends PsiNamedElement & PyElement> Collection<T> filterNameless(@NotNull final Collection<T> elementsToFilter) {
- return Collections2.filter(elementsToFilter, new NamelessFilter<T>());
- }
-
- /**
* Returns list of elements that may require reference storing aid from {@link com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil#rememberNamedReferences(com.intellij.psi.PsiElement, String...)}
*
* @param elements members chosen by user. In most cases members their selves could be stored, but different managers may support other strategies
@@ -227,6 +216,7 @@
/**
* Moves element from one class to another. Returns members that may require reference restoring aid from
* ({@link com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil#restoreNamedReferences(com.intellij.psi.PsiElement)})
+ * Sort members according to their dependncies, before calling this method
*
* @see #getElementsToStoreReferences(java.util.Collection)
*/
@@ -357,13 +347,6 @@
}
}
- private static class NamelessFilter<T extends PyElement & PsiNamedElement> extends NotNullPredicate<T> {
- @Override
- public boolean applyNotNull(@NotNull final T input) {
- return input.getName() != null;
- }
- }
-
private static class FindByElement extends NotNullPredicate<PyMemberInfo<PyElement>> {
private final PyElement myPyElement;
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java
index 7cba0a2..52c32d9 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java
@@ -1,7 +1,8 @@
package com.jetbrains.python.refactoring.classes.membersManager;
+import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
+import com.google.common.collect.FluentIterable;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -35,6 +36,7 @@
{PyNames.PROPERTY, PyNames.CLASSMETHOD, PyNames.STATICMETHOD};
public static final String ABC_META_PACKAGE = "abc";
+ private static final NoPropertiesPredicate NO_PROPERTIES = new NoPropertiesPredicate();
MethodsManager() {
super(PyFunction.class);
@@ -54,16 +56,15 @@
@NotNull
@Override
protected MultiMap<PyClass, PyElement> getDependencies(@NotNull final PyElement member) {
- final MultiMap<PyClass, PyElement> result = new MultiMap<PyClass, PyElement>();
- member.accept(new MyPyRecursiveElementVisitor(result));
-
- return result;
+ final MyPyRecursiveElementVisitor visitor = new MyPyRecursiveElementVisitor();
+ member.accept(visitor);
+ return visitor.myResult;
}
@NotNull
@Override
- protected List<PyElement> getMembersCouldBeMoved(@NotNull final PyClass pyClass) {
- return Lists.<PyElement>newArrayList(filterNameless(Arrays.asList(pyClass.getMethods())));
+ protected List<? extends PyElement> getMembersCouldBeMoved(@NotNull final PyClass pyClass) {
+ return FluentIterable.from(Arrays.asList(pyClass.getMethods())).filter(new NamelessFilter<PyFunction>()).filter(NO_PROPERTIES).toList();
}
@Override
@@ -74,7 +75,7 @@
final Collection<PyFunction> methodsToAbstract = fetchElements(Collections2.filter(members, new AbstractFilter(true)));
makeMethodsAbstract(methodsToAbstract, to);
- return moveMethods(from, methodsToMove, to);
+ return moveMethods(from, methodsToMove, true, to);
}
/**
@@ -156,9 +157,10 @@
* @param from source
* @param methodsToMove what to move
* @param to where
+ * @param skipIfExist skip (do not add) if method already exists
* @return newly added methods
*/
- private static List<PyElement> moveMethods(final PyClass from, final Collection<PyFunction> methodsToMove, final PyClass... to) {
+ static List<PyElement> moveMethods(final PyClass from, final Collection<PyFunction> methodsToMove, final boolean skipIfExist, final PyClass... to) {
final List<PyElement> result = new ArrayList<PyElement>();
for (final PyClass destClass : to) {
//We move copies here because there may be several destinations
@@ -168,7 +170,7 @@
copies.add(newMethod);
}
- result.addAll(PyClassRefactoringUtil.copyMethods(copies, destClass));
+ result.addAll(PyClassRefactoringUtil.copyMethods(copies, destClass, skipIfExist));
}
deleteElements(methodsToMove);
@@ -251,14 +253,7 @@
}
}
- private static class MyPyRecursiveElementVisitor extends PyRecursiveElementVisitor {
- @NotNull
- private final MultiMap<PyClass, PyElement> myResult;
-
- private MyPyRecursiveElementVisitor(@NotNull final MultiMap<PyClass, PyElement> result) {
- myResult = result;
- }
-
+ private static class MyPyRecursiveElementVisitor extends PyRecursiveElementVisitorWithResult {
@Override
public void visitPyCallExpression(final PyCallExpression node) {
// TODO: refactor, messy code
@@ -281,4 +276,14 @@
}
}
}
+
+ /**
+ * Filter out property setters and getters
+ */
+ private static class NoPropertiesPredicate implements Predicate<PyFunction> {
+ @Override
+ public boolean apply(@NotNull PyFunction input) {
+ return input.getProperty() == null;
+ }
+ }
}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/NamelessFilter.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/NamelessFilter.java
new file mode 100644
index 0000000..ec688e3
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/NamelessFilter.java
@@ -0,0 +1,21 @@
+package com.jetbrains.python.refactoring.classes.membersManager;
+
+import com.intellij.psi.PsiNamedElement;
+import com.jetbrains.NotNullPredicate;
+import com.jetbrains.python.psi.PyElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Filters out named elements (ones that subclasses {@link com.intellij.psi.PsiNamedElement}) and {@link com.jetbrains.python.psi.PyElement})
+ * that are null or has null name.
+ * You need it sometimes when code has errors (i.e. bad formatted code with annotation may treat annotation as method with null name.
+ *
+* @author Ilya.Kazakevich
+*/
+class NamelessFilter<T extends PyElement & PsiNamedElement> extends NotNullPredicate<T> {
+
+ @Override
+ public boolean applyNotNull(@NotNull final T input) {
+ return input.getName() != null;
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/PropertiesManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PropertiesManager.java
new file mode 100644
index 0000000..142bb31
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PropertiesManager.java
@@ -0,0 +1,210 @@
+package com.jetbrains.python.refactoring.classes.membersManager;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.containers.MultiMap;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Plugin that moves class properties.
+ * It represents property (whatever old or new) as one of its methods.
+ *
+ * @author Ilya.Kazakevich
+ */
+class PropertiesManager extends MembersManager<PyElement> {
+
+ PropertiesManager() {
+ super(PyElement.class);
+ }
+
+
+ @NotNull
+ @Override
+ protected List<? extends PyElement> getMembersCouldBeMoved(@NotNull final PyClass pyClass) {
+ final List<PyElement> elements = new ArrayList<PyElement>(pyClass.getProperties().size());
+ for (final Property property : pyClass.getProperties().values()) {
+ elements.add(getElement(property));
+ }
+ return elements;
+ }
+
+ @NotNull
+ private static PyElement getElement(@NotNull final Property property) {
+ final Callable getter = property.getGetter().valueOrNull();
+ final Callable setter = property.getSetter().valueOrNull();
+ final Callable deleter = property.getDeleter().valueOrNull();
+
+ if (getter != null) {
+ return getter;
+ }
+ else if (setter != null) {
+ return setter;
+ }
+ else if (deleter != null) {
+ return deleter;
+ }
+ else {
+ final PyTargetExpression site = property.getDefinitionSite();
+ assert site != null : "Property has no methods nor declaration. That is not property";
+ return site;
+ }
+ }
+
+ @NotNull
+ private static Property getProperty(@NotNull final PyClass pyClass, @NotNull final PyElement element) {
+ final Collection<Property> properties = pyClass.getProperties().values();
+ if (element instanceof PyTargetExpression) {
+ return getPropertyByTargetExpression(properties, (PyTargetExpression)element);
+ }
+ if (element instanceof PyFunction) {
+ return getPropertyByFunction(properties, (PyFunction)element);
+ }
+ throw new IllegalArgumentException("Not function nor target");
+ }
+
+ @NotNull
+ private static Property getPropertyByFunction(@NotNull final Collection<Property> properties,
+ @NotNull final PyFunction functionToSearch) {
+ for (final Property property : properties) {
+ for (final PyFunction function : getAllFunctions(property)) {
+ if (function.equals(functionToSearch)) {
+ return property;
+ }
+ }
+ }
+ throw new IllegalArgumentException("No property found");
+ }
+
+ @NotNull
+ private static Property getPropertyByTargetExpression(@NotNull final Iterable<Property> properties,
+ @NotNull final PyTargetExpression element) {
+ for (final Property property : properties) {
+ if (element.equals(property.getDefinitionSite())) {
+ return property;
+ }
+ }
+ throw new IllegalArgumentException("No property found");
+ }
+
+ @NotNull
+ private static Collection<PyFunction> getAllFunctions(@NotNull final Property property) {
+ final Collection<PyFunction> result = new ArrayList<PyFunction>(3);
+ final Callable getter = property.getGetter().valueOrNull();
+ final Callable setter = property.getSetter().valueOrNull();
+ final Callable deleter = property.getDeleter().valueOrNull();
+
+ if (getter instanceof PyFunction) {
+ result.add((PyFunction)getter);
+ }
+ if (setter instanceof PyFunction) {
+ result.add((PyFunction)setter);
+ }
+ if (deleter instanceof PyFunction) {
+ result.add((PyFunction)deleter);
+ }
+ return result;
+ }
+
+ @Override
+ protected Collection<PyElement> moveMembers(@NotNull final PyClass from,
+ @NotNull final Collection<PyMemberInfo<PyElement>> members,
+ @NotNull final PyClass... to) {
+ final Collection<PyElement> result = new ArrayList<PyElement>();
+
+ final Collection<PyElement> elements = fetchElements(members);
+ for (final PyElement element : elements) {
+ final Property property = getProperty(from, element);
+ final Collection<PyFunction> functions = getAllFunctions(property);
+ MethodsManager.moveMethods(from, functions, false, to);
+ final PyTargetExpression definitionSite = property.getDefinitionSite();
+ if (definitionSite != null) {
+ final PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(definitionSite, PyAssignmentStatement.class);
+ ClassFieldsManager.moveAssignmentsImpl(from, Collections.singleton(assignmentStatement), to);
+ }
+ }
+ return result;
+ }
+
+ @NotNull
+ @Override
+ public PyMemberInfo<PyElement> apply(@NotNull final PyElement input) {
+ return new PyMemberInfo<PyElement>(input, false, getName(input), false, this, false);
+ }
+
+ private static String getName(@NotNull final PyElement input) {
+ final PyClass clazz = PsiTreeUtil.getParentOfType(input, PyClass.class);
+ assert clazz != null : "Element not declared in class";
+ final Property property = getProperty(clazz, input);
+ return property.getName();
+ }
+
+ @Override
+ public boolean hasConflict(@NotNull final PyElement member, @NotNull final PyClass aClass) {
+ return false;
+ }
+
+ @NotNull
+ @Override
+ protected MultiMap<PyClass, PyElement> getDependencies(@NotNull final PyElement member) {
+ final PyRecursiveElementVisitorWithResult visitor = new PyReferenceVisitor();
+ member.accept(visitor);
+
+ return visitor.myResult;
+ }
+
+ @NotNull
+ @Override
+ protected Collection<PyElement> getDependencies(@NotNull final MultiMap<PyClass, PyElement> usedElements) {
+ return Collections.emptyList();
+ }
+
+ private static class PyReferenceVisitor extends PyRecursiveElementVisitorWithResult {
+
+
+ @Override
+ public void visitPyExpression(final PyExpression node) {
+ final PsiReference reference = node.getReference();
+ if (reference == null) {
+ return;
+ }
+
+ final PsiElement declaration = reference.resolve();
+ if (!(declaration instanceof PyFunction)) {
+ return;
+ }
+
+ final PyFunction function = (PyFunction)declaration;
+ final Property property = function.getProperty();
+ if (property == null) {
+ return;
+ }
+
+ final PyClass aClass = function.getContainingClass();
+ if (aClass == null) {
+ return;
+ }
+ final Collection<PyFunction> functions = getAllFunctions(property);
+ for (final PyFunction pyFunction : functions) {
+ final PyClass functionClass = pyFunction.getContainingClass();
+ if (functionClass != null) {
+ myResult.putValue(functionClass, pyFunction);
+ }
+ }
+
+ final PyTargetExpression definitionSite = property.getDefinitionSite();
+ if (definitionSite != null) {
+ final PyClass pyClass = PsiTreeUtil.getParentOfType(definitionSite, PyClass.class);
+ if (pyClass != null) {
+ myResult.putValue(pyClass, definitionSite);
+ }
+ }
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyRecursiveElementVisitorWithResult.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyRecursiveElementVisitorWithResult.java
new file mode 100644
index 0000000..14ba3ae
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyRecursiveElementVisitorWithResult.java
@@ -0,0 +1,19 @@
+package com.jetbrains.python.refactoring.classes.membersManager;
+
+import com.intellij.util.containers.MultiMap;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.psi.PyRecursiveElementVisitor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Recursive visitor with multimap, to be used for {@link com.jetbrains.python.refactoring.classes.membersManager.MembersManager#getDependencies(com.jetbrains.python.psi.PyElement)}
+ */
+class PyRecursiveElementVisitorWithResult extends PyRecursiveElementVisitor {
+ @NotNull
+ protected final MultiMap<PyClass, PyElement> myResult;
+
+ PyRecursiveElementVisitorWithResult() {
+ myResult = new MultiMap<PyClass, PyElement>();
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java b/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java
index 7f77401..f479d10 100644
--- a/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java
@@ -207,7 +207,7 @@
if (type != null && type != PyNoneType.INSTANCE) {
String typeName = type.getName();
if (typeName != null) {
- if (type.isBuiltin(context)) {
+ if (type.isBuiltin()) {
typeName = typeName.substring(0, 1);
}
candidates.addAll(NameSuggesterUtil.generateNamesByType(typeName));
diff --git a/python/src/com/jetbrains/python/remote/PyRemoteSdkAdditionalDataBase.java b/python/src/com/jetbrains/python/remote/PyRemoteSdkAdditionalDataBase.java
index deb8030..66cceb1 100644
--- a/python/src/com/jetbrains/python/remote/PyRemoteSdkAdditionalDataBase.java
+++ b/python/src/com/jetbrains/python/remote/PyRemoteSdkAdditionalDataBase.java
@@ -15,10 +15,10 @@
*/
package com.jetbrains.python.remote;
-import com.intellij.remotesdk2.RemoteSdkAdditionalData2;
+import com.intellij.remote.RemoteSdkAdditionalData;
/**
* @author traff
*/
-public interface PyRemoteSdkAdditionalDataBase extends RemoteSdkAdditionalData2<PyRemoteSdkCredentials>, PySkeletonsPathAware {
+public interface PyRemoteSdkAdditionalDataBase extends RemoteSdkAdditionalData<PyRemoteSdkCredentials>, PySkeletonsPathAware {
}
diff --git a/python/src/com/jetbrains/python/remote/PyRemoteSdkCredentials.java b/python/src/com/jetbrains/python/remote/PyRemoteSdkCredentials.java
index 5b5fc9b..d9a9f04 100644
--- a/python/src/com/jetbrains/python/remote/PyRemoteSdkCredentials.java
+++ b/python/src/com/jetbrains/python/remote/PyRemoteSdkCredentials.java
@@ -15,7 +15,7 @@
*/
package com.jetbrains.python.remote;
-import com.intellij.remotesdk.RemoteSdkCredentials;
+import com.intellij.remote.RemoteSdkCredentials;
/**
* @author yole
diff --git a/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java b/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java
index 40e34f1..4276ed8 100644
--- a/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java
+++ b/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java
@@ -27,9 +27,8 @@
import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.remotesdk.RemoteInterpreterException;
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.remotesdk.RemoteSshProcess;
+import com.intellij.remote.*;
+import com.intellij.remote.RemoteSdkException;
import com.intellij.util.NullableConsumer;
import com.intellij.util.PathMappingSettings;
import com.jetbrains.python.PythonHelpersLocator;
@@ -49,21 +48,21 @@
public final static ExtensionPointName<PythonRemoteInterpreterManager> EP_NAME =
ExtensionPointName.create("Pythonid.remoteInterpreterManager");
public static final String WEB_DEPLOYMENT_PLUGIN_IS_DISABLED =
- "Remote interpreter can't be executed. Please enable the Remote Hosts Access plugin.";
+ "Remote interpreter can't be executed. Please enable the Remote Hosts Access plugin."; //TODO: this message is incorrect
public abstract ProcessHandler startRemoteProcess(@Nullable Project project,
@NotNull PyRemoteSdkCredentials data,
@NotNull GeneralCommandLine commandLine,
@Nullable
PathMappingSettings mappingSettings)
- throws RemoteInterpreterException;
+ throws RemoteSdkException;
public abstract ProcessHandler startRemoteProcessWithPid(@Nullable Project project,
@NotNull PyRemoteSdkCredentials data,
@NotNull GeneralCommandLine commandLine,
@Nullable
PathMappingSettings mappingSettings)
- throws RemoteInterpreterException;
+ throws RemoteSdkException;
public abstract void addRemoteSdk(Project project, Component parentComponent, Collection<Sdk> existingSdks,
NullableConsumer<Sdk> sdkCallback);
@@ -74,13 +73,13 @@
String[] command,
@Nullable String workingDir,
boolean askForSudo)
- throws RemoteInterpreterException;
+ throws RemoteSdkException;
@NotNull
public abstract RemoteSshProcess createRemoteProcess(@Nullable Project project,
@NotNull RemoteSdkCredentials data,
@NotNull GeneralCommandLine commandLine, boolean allocatePty)
- throws RemoteInterpreterException;
+ throws RemoteSdkException;
public abstract boolean editSdk(@NotNull Project project, @NotNull SdkModificator sdkModificator, Collection<Sdk> existingSdks);
@@ -140,6 +139,8 @@
public abstract SdkAdditionalData loadRemoteSdkData(Sdk sdk, Element additional);
+ public abstract boolean testConnection(RemoteCredentials credentials);
+
public static class PyRemoteInterpreterExecutionException extends ExecutionException {
public PyRemoteInterpreterExecutionException() {
@@ -153,5 +154,11 @@
super(WEB_DEPLOYMENT_PLUGIN_IS_DISABLED);
}
}
+
+ public abstract RemoteCredentials getVagrantRemoteCredentials(VagrantBasedCredentialsHolder data);
+
+ public abstract void checkVagrantStatus(VagrantBasedCredentialsHolder data);
+
+ public abstract RemoteCredentials getCredentialsBySftpServerId(String id);
}
diff --git a/python/src/com/jetbrains/python/remote/RemoteDebuggableProcessHandler.java b/python/src/com/jetbrains/python/remote/RemoteDebuggableProcessHandler.java
index 514fc2a..db2b329 100644
--- a/python/src/com/jetbrains/python/remote/RemoteDebuggableProcessHandler.java
+++ b/python/src/com/jetbrains/python/remote/RemoteDebuggableProcessHandler.java
@@ -15,7 +15,7 @@
*/
package com.jetbrains.python.remote;
-import com.intellij.remotesdk.RemoteProcessHandlerBase;
+import com.intellij.remote.RemoteProcessHandlerBase;
import com.jetbrains.python.debugger.PyDebugProcess;
import com.jetbrains.python.debugger.PyPositionConverter;
diff --git a/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java b/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java
index 5941d5f..673b87d 100644
--- a/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java
+++ b/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java
@@ -24,10 +24,8 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkAdditionalData;
-import com.intellij.remotesdk2.RemoteSdkAdditionalData2;
import com.intellij.util.PathMappingSettings;
import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase;
-import com.jetbrains.python.remote.PyRemoteSdkCredentials;
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
diff --git a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.form b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.form
deleted file mode 100644
index ea6172e..0000000
--- a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.form
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.sdk.CreateVirtualEnvDialog">
- <grid id="cbd77" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
- <margin top="0" left="0" bottom="0" right="0"/>
- <constraints>
- <xy x="48" y="54" width="550" height="342"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="23a50" class="javax.swing.JComboBox" binding="mySdkCombo">
- <constraints>
- <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- </component>
- <vspacer id="b277d">
- <constraints>
- <grid row="5" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
- </constraints>
- </vspacer>
- <component id="48fd" class="com.intellij.ui.components.JBLabel">
- <constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value="&Base interpreter:"/>
- </properties>
- </component>
- <component id="a1259" class="javax.swing.JTextField" binding="myName">
- <constraints>
- <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
- <preferred-size width="150" height="-1"/>
- </grid>
- </constraints>
- <properties/>
- </component>
- <component id="29c55" class="com.intellij.ui.components.JBLabel">
- <constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <labelFor value="a1259"/>
- <text value="&Name:"/>
- </properties>
- </component>
- <component id="1b80c" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myDestination">
- <constraints>
- <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- </component>
- <component id="42f44" class="com.intellij.ui.components.JBLabel">
- <constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value="&Location:"/>
- </properties>
- </component>
- <component id="41e08" class="com.intellij.ui.components.JBCheckBox" binding="myMakeAvailableToAllProjectsCheckbox">
- <constraints>
- <grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <selected value="false"/>
- <text value="Make available to &all projects"/>
- </properties>
- </component>
- <component id="d10a9" class="com.intellij.ui.components.JBCheckBox" binding="mySitePackagesCheckBox">
- <constraints>
- <grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <selected value="false"/>
- <text value="&Inherit global site-packages"/>
- </properties>
- </component>
- </children>
- </grid>
-</form>
diff --git a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java
index 1043866..e2cfe9c 100644
--- a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java
+++ b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java
@@ -29,16 +29,21 @@
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
+import com.intellij.openapi.ui.ComboBox;
+import com.intellij.openapi.ui.FixedSizeButton;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.LocationNameFieldsBinding;
-import com.intellij.remotesdk.RemoteSdkCredentialsHolder;
+import com.intellij.remote.RemoteSdkCredentialsHolder;
import com.intellij.ui.CollectionComboBoxModel;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.components.JBCheckBox;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.util.NullableConsumer;
import com.intellij.util.PathUtil;
import com.intellij.util.PlatformUtils;
import com.jetbrains.python.packaging.PyExternalProcessException;
@@ -91,7 +96,7 @@
final String name =
SdkConfigurationUtil.createUniqueSdkName(PythonSdkType.getInstance(), sdkHome.getPath(), allSdks);
final ProjectJdkImpl sdk = new ProjectJdkImpl(name, PythonSdkType.getInstance());
- sdk.setHomePath(sdkHome.getPath());
+ sdk.setHomePath(FileUtil.toSystemDependentName(sdkHome.getPath()));
callback.virtualEnvCreated(sdk, associateWithProject);
PythonSdkType.setupSdkPaths(sdk, myProject, null);
}
@@ -111,17 +116,19 @@
setupDialog(null, allSdks, suggestedBaseSdk);
}
- private void setupDialog(Project project, List<Sdk> allSdks, @Nullable Sdk suggestedBaseSdk) {
+ private void setupDialog(Project project, final List<Sdk> allSdks, @Nullable Sdk suggestedBaseSdk) {
myProject = project;
+ layoutPanel(allSdks);
+
init();
setTitle("Create Virtual Environment");
+ Iterables.removeIf(allSdks, new Predicate<Sdk>() {
+ @Override
+ public boolean apply(Sdk s) {
+ return PythonSdkType.isInvalid(s) || PythonSdkType.isVirtualEnv(s) || RemoteSdkCredentialsHolder.isRemoteSdk(s.getHomePath());
+ }
+ });
if (suggestedBaseSdk == null && allSdks.size() > 0) {
- Iterables.removeIf(allSdks, new Predicate<Sdk>() {
- @Override
- public boolean apply(Sdk s) {
- return PythonSdkType.isInvalid(s) || PythonSdkType.isVirtualEnv(s) || RemoteSdkCredentialsHolder.isRemoteSdk(s.getHomePath());
- }
- });
List<Sdk> sortedSdks = new ArrayList<Sdk>(allSdks);
Collections.sort(sortedSdks, new PreferredSdkComparator());
suggestedBaseSdk = sortedSdks.get(0);
@@ -139,16 +146,19 @@
final VirtualFile file = VirtualEnvSdkFlavor.getDefaultLocation();
- if (file != null)
+ if (file != null) {
myInitialPath = file.getPath();
+ }
else {
final String savedPath = PyPackageService.getInstance().getVirtualEnvBasePath();
- if (!StringUtil.isEmptyOrSpaces(savedPath))
+ if (!StringUtil.isEmptyOrSpaces(savedPath)) {
myInitialPath = savedPath;
+ }
else if (myProject != null) {
final VirtualFile baseDir = myProject.getBaseDir();
- if (baseDir != null)
+ if (baseDir != null) {
myInitialPath = baseDir.getPath();
+ }
}
}
@@ -167,6 +177,87 @@
checkValid();
}
+ private void layoutPanel(final List<Sdk> allSdks) {
+ final GridBagLayout layout = new GridBagLayout();
+ myMainPanel = new JPanel(layout);
+
+ final GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(2,2,2,2);
+
+ c.gridx = 0;
+ c.gridy = 0;
+ c.weightx = 0.0;
+ myMainPanel.add(new JBLabel("Name:"), c);
+
+ c.gridx = 1;
+ c.gridy = 0;
+ c.gridwidth = 2;
+ c.weightx = 1.0;
+ myName = new JTextField();
+ myMainPanel.add(myName, c);
+
+ c.gridx = 0;
+ c.gridy = 1;
+ c.gridwidth = 1;
+ c.weightx = 0.0;
+ myMainPanel.add(new JBLabel("Location:"), c);
+
+ c.gridx = 1;
+ c.gridy = 1;
+ c.gridwidth = 2;
+ c.weightx = 1.0;
+ myDestination = new TextFieldWithBrowseButton();
+ myMainPanel.add(myDestination, c);
+
+ c.gridx = 0;
+ c.gridy = 2;
+ c.gridwidth = 1;
+ c.weightx = 0.0;
+ myMainPanel.add(new JBLabel("Base interpreter:"), c);
+
+ c.gridx = 1;
+ c.gridy = 2;
+ mySdkCombo = new ComboBox();
+ c.insets = new Insets(2,2,2,2);
+ c.weightx = 1.0;
+ myMainPanel.add(mySdkCombo, c);
+
+ c.gridx = 2;
+ c.gridy = 2;
+ c.insets = new Insets(0,0,2,2);
+ c.weightx = 0.0;
+ FixedSizeButton button = new FixedSizeButton();
+ button.setPreferredSize(myDestination.getButton().getPreferredSize());
+ myMainPanel.add(button, c);
+
+ c.gridx = 0;
+ c.gridy = 3;
+ c.gridwidth = 3;
+ c.insets = new Insets(2,2,2,2);
+ mySitePackagesCheckBox = new JBCheckBox("Inherit global site-packages");
+ myMainPanel.add(mySitePackagesCheckBox, c);
+
+ c.gridx = 0;
+ c.gridy = 4;
+ myMakeAvailableToAllProjectsCheckbox = new JBCheckBox("Make available to all projects");
+ myMainPanel.add(myMakeAvailableToAllProjectsCheckbox, c);
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ SdkConfigurationUtil.createSdk(myProject, allSdks.toArray(new Sdk[allSdks.size() - 1]), new NullableConsumer<Sdk>() {
+ @Override
+ public void consume(@Nullable Sdk sdk) {
+ if (sdk == null) return;
+ if (!allSdks.contains(sdk)) {
+ allSdks.add(sdk);
+ }
+ updateSdkList(allSdks, sdk);
+ }
+ }, false, PythonSdkType.getInstance());
+ }
+ });
+ }
+
private void checkValid() {
final String projectName = myName.getText();
if (new File(getDestination()).exists()) {
diff --git a/python/src/com/jetbrains/python/sdk/PySdkUtil.java b/python/src/com/jetbrains/python/sdk/PySdkUtil.java
index 4185da7..d8a2c2f 100644
--- a/python/src/com/jetbrains/python/sdk/PySdkUtil.java
+++ b/python/src/com/jetbrains/python/sdk/PySdkUtil.java
@@ -25,8 +25,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
-import com.intellij.remotesdk.RemoteCredentials;
-import com.intellij.remotesdk2.RemoteSdkAdditionalData2;
+import com.intellij.remote.RemoteSdkAdditionalData;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NonNls;
@@ -214,7 +213,7 @@
}
public static boolean isRemote(@Nullable Sdk sdk) {
- return sdk != null && sdk.getSdkAdditionalData() instanceof RemoteSdkAdditionalData2;
+ return sdk != null && sdk.getSdkAdditionalData() instanceof RemoteSdkAdditionalData;
}
public static boolean isElementInSkeletons(@NotNull final PsiElement element) {
diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkAdditionalData.java b/python/src/com/jetbrains/python/sdk/PythonSdkAdditionalData.java
index c268022..c0a4226 100644
--- a/python/src/com/jetbrains/python/sdk/PythonSdkAdditionalData.java
+++ b/python/src/com/jetbrains/python/sdk/PythonSdkAdditionalData.java
@@ -35,6 +35,8 @@
import java.util.List;
import java.util.Set;
+import static com.intellij.openapi.util.JDOMExternalizer.loadStringsList;
+
/**
* @author traff
*/
@@ -58,16 +60,11 @@
}
public Object clone() throws CloneNotSupportedException {
- try {
- final PythonSdkAdditionalData copy = (PythonSdkAdditionalData)super.clone();
- copy.setAddedPaths(getAddedPaths());
- copy.setExcludedPaths(getExcludedPaths());
- copy.setAssociatedProjectPath(getAssociatedProjectPath());
- return copy;
- }
- catch (CloneNotSupportedException e) {
- return null;
- }
+ final PythonSdkAdditionalData copy = new PythonSdkAdditionalData(myFlavor);
+ copy.setAddedPaths(getAddedPaths());
+ copy.setExcludedPaths(getExcludedPaths());
+ copy.setAssociatedProjectPath(getAssociatedProjectPath());
+ return copy;
}
public Set<SimpleProjectRoot> getAddedPaths() {
@@ -181,16 +178,6 @@
return files;
}
- protected static List<String> loadStringsList(Element element, String rootName, String attrName) {
- final List<String> paths = new LinkedList<String>();
- if (element != null) {
- @NotNull final List list = element.getChildren(rootName);
- for (Object o : list) {
- paths.add(((Element)o).getAttribute(attrName).getValue());
- }
- }
- return paths;
- }
public Set<VirtualFile> getAddedPathFiles() {
return getPathsAsVirtualFiles(myAddedPaths);
diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java b/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java
index df04801..3e0d4ff 100644
--- a/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java
+++ b/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java
@@ -40,7 +40,7 @@
import java.util.List;
public class PythonSdkDetailsStep extends BaseListPopupStep<String> {
- private static DialogWrapper myMore;
+ private DialogWrapper myMore;
private final Project myProject;
private final Component myOwnerComponent;
private final Sdk[] myExistingSdks;
@@ -55,21 +55,20 @@
final Sdk[] existingSdks,
DialogWrapper moreDialog,
JComponent ownerComponent, final Point popupPoint,
- final boolean showMore,
final NullableConsumer<Sdk> callback) {
- myMore = moreDialog;
- final ListPopupStep sdkHomesStep = new PythonSdkDetailsStep(project, ownerComponent, existingSdks, showMore, callback);
+
+ final ListPopupStep sdkHomesStep = new PythonSdkDetailsStep(project, moreDialog, ownerComponent, existingSdks, callback);
final ListPopup popup = JBPopupFactory.getInstance().createListPopup(sdkHomesStep);
popup.showInScreenCoordinates(ownerComponent, popupPoint);
}
public PythonSdkDetailsStep(Project project,
- Component ownerComponent,
+ DialogWrapper moreDialog, Component ownerComponent,
Sdk[] existingSdks,
- boolean showMore,
NullableConsumer<Sdk> callback) {
- super(null, getAvailableOptions(showMore));
+ super(null, getAvailableOptions(moreDialog != null));
myProject = project;
+ myMore = moreDialog;
myOwnerComponent = ownerComponent;
myExistingSdks = existingSdks;
myCallback = callback;
@@ -154,7 +153,7 @@
final List<PythonSdkFlavor> flavors = PythonSdkFlavor.getApplicableFlavors(false);
for (PythonSdkFlavor flavor : flavors) {
final Collection<String> strings = flavor.suggestHomePaths();
- for (String string : strings) {
+ for (String string : SdkConfigurationUtil.filterExistingPaths(PythonSdkType.getInstance(), strings, myExistingSdks)) {
allSdks.add(new PyDetectedSdk(string));
}
}
diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java
index 6aa0c6d..b13cb76 100644
--- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java
+++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java
@@ -51,8 +51,8 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.reference.SoftReference;
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.remotesdk.RemoteSdkCredentialsHolder;
+import com.intellij.remote.RemoteSdkCredentials;
+import com.intellij.remote.RemoteSdkCredentialsHolder;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.NullableConsumer;
@@ -282,7 +282,7 @@
final Point point = parentComponent.getMousePosition();
SwingUtilities.convertPointToScreen(point, parentComponent);
PythonSdkDetailsStep
- .show(project, sdkModel.getSdks(), null, parentComponent, point, false, new NullableConsumer<Sdk>() {
+ .show(project, sdkModel.getSdks(), null, parentComponent, point, new NullableConsumer<Sdk>() {
@Override
public void consume(@Nullable Sdk sdk) {
if (sdk != null) {
@@ -407,18 +407,19 @@
}
public static String suggestSdkNameFromVersion(String sdkHome, String version) {
- final String short_home_name = FileUtil.getLocationRelativeToUserHome(sdkHome);
+ sdkHome = FileUtil.toSystemDependentName(sdkHome);
+ final String shortHomeName = FileUtil.getLocationRelativeToUserHome(sdkHome);
if (version != null) {
- File virtualenv_root = getVirtualEnvRoot(sdkHome);
- if (virtualenv_root != null) {
- version += " virtualenv at " + FileUtil.getLocationRelativeToUserHome(virtualenv_root.getAbsolutePath());
+ File virtualEnvRoot = getVirtualEnvRoot(sdkHome);
+ if (virtualEnvRoot != null) {
+ version += " virtualenv at " + FileUtil.getLocationRelativeToUserHome(virtualEnvRoot.getAbsolutePath());
}
else {
- version += " (" + short_home_name + ")";
+ version += " (" + shortHomeName + ")";
}
}
else {
- version = "Unknown at " + short_home_name;
+ version = "Unknown at " + shortHomeName;
} // last resort
return version;
}
@@ -480,10 +481,10 @@
if (flavor != null) {
VirtualFile sdkPath = flavor.getSdkPath(homePath);
if (sdkPath != null) {
- return sdkPath.getPath();
+ return FileUtil.toSystemDependentName(sdkPath.getPath());
}
}
- return path;
+ return FileUtil.toSystemDependentName(path);
}
public void setupSdkPaths(@NotNull final Sdk sdk) {
@@ -658,9 +659,9 @@
}
public static void addSdkRoot(SdkModificator sdkModificator, String path) {
- VirtualFile child = LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
- if (child != null) {
- addSdkRoot(sdkModificator, child);
+ final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
+ if (file != null) {
+ addSdkRoot(sdkModificator, file);
}
else {
LOG.info("Bogus sys.path entry " + path);
@@ -668,19 +669,26 @@
}
private static void addSdkRoot(@NotNull SdkModificator sdkModificator, @NotNull VirtualFile child) {
- @NonNls String suffix = child.getExtension();
- if (suffix != null) suffix = suffix.toLowerCase(); // Why on earth empty suffix is null and not ""?
- VirtualFile toAdd = child;
- if ((!child.isDirectory()) && ("zip".equals(suffix) || "egg".equals(suffix))) {
+ // NOTE: Files marked as library sources are not considered part of project source. Since the directory of the project the
+ // user is working on is included in PYTHONPATH with many configurations (e.g. virtualenv), we must not mark SDK paths as
+ // library sources, only as classes.
+ sdkModificator.addRoot(getSdkRootVirtualFile(child), OrderRootType.CLASSES);
+ }
+
+ @NotNull
+ public static VirtualFile getSdkRootVirtualFile(@NotNull VirtualFile path) {
+ String suffix = path.getExtension();
+ if (suffix != null) {
+ suffix = suffix.toLowerCase(); // Why on earth empty suffix is null and not ""?
+ }
+ if ((!path.isDirectory()) && ("zip".equals(suffix) || "egg".equals(suffix))) {
// a .zip / .egg file must have its root extracted first
- toAdd = JarFileSystem.getInstance().getJarRootForLocalFile(child);
+ final VirtualFile jar = JarFileSystem.getInstance().getJarRootForLocalFile(path);
+ if (jar != null) {
+ return jar;
+ }
}
- if (toAdd != null) {
- // NOTE: Files marked as library sources are not considered part of project source. Since the directory of the project the
- // user is working on is included in PYTHONPATH with many configurations (e.g. virtualenv), we must not mark SDK paths as
- // library sources, only as classes.
- sdkModificator.addRoot(toAdd, OrderRootType.CLASSES);
- }
+ return path;
}
public static String getSkeletonsPath(String basePath, String sdkHome) {
diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java b/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java
index 2cc749f..a964fa9 100644
--- a/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java
+++ b/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java
@@ -31,6 +31,7 @@
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.startup.StartupActivity;
import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsUtil;
@@ -38,7 +39,6 @@
import org.jetbrains.annotations.NotNull;
import java.io.File;
-import java.io.IOException;
import java.util.*;
/**
@@ -135,7 +135,7 @@
}
}
- private static void updateSysPath(final Sdk sdk) throws InvalidSdkException {
+ private static void updateSysPath(@NotNull final Sdk sdk) throws InvalidSdkException {
long start_time = System.currentTimeMillis();
final List<String> sysPath = PythonSdkType.getSysPath(sdk.getHomePath());
final VirtualFile file = PyUserSkeletonsUtil.getUserSkeletonsDirectory();
@@ -151,9 +151,29 @@
LOG.info("Updating sys.path took " + (System.currentTimeMillis() - start_time) + " ms");
}
- private static void updateSdkPath(Sdk sdk, List<String> sysPath) {
+ /**
+ * Updates SDK based on sys.path and cleans legacy information up.
+ */
+ private static void updateSdkPath(@NotNull Sdk sdk, @NotNull List<String> sysPath) {
+ final SdkModificator modificator = sdk.getSdkModificator();
+ boolean changed = addNewSysPathEntries(sdk, modificator, sysPath);
+ changed = removeSourceRoots(sdk, modificator) || changed;
+ changed = removeDuplicateClassRoots(sdk, modificator) || changed;
+ if (changed) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ modificator.commitChanges();
+ }
+ });
+ }
+ }
+
+ /**
+ * Adds new CLASSES entries found in sys.path.
+ */
+ private static boolean addNewSysPathEntries(@NotNull Sdk sdk, @NotNull SdkModificator modificator, @NotNull List<String> sysPath) {
final List<VirtualFile> oldRoots = Arrays.asList(sdk.getRootProvider().getFiles(OrderRootType.CLASSES));
- final VirtualFile[] sourceRoots = sdk.getRootProvider().getFiles(OrderRootType.SOURCES);
PythonSdkAdditionalData additionalData = sdk.getSdkAdditionalData() instanceof PythonSdkAdditionalData
? (PythonSdkAdditionalData)sdk.getSdkAdditionalData()
: null;
@@ -166,37 +186,49 @@
newRoots.add(root);
}
}
- if (!newRoots.isEmpty() || sourceRoots.length > 0) {
- final SdkModificator modificator = sdk.getSdkModificator();
+ if (!newRoots.isEmpty()) {
for (String root : newRoots) {
PythonSdkType.addSdkRoot(modificator, root);
}
- modificator.removeRoots(OrderRootType.SOURCES);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- modificator.commitChanges();
- }
- });
- }
- }
-
- private static boolean wasOldRoot(String root, Collection<VirtualFile> virtualFiles) {
- String rootPath = canonicalize(root);
- for (VirtualFile virtualFile : virtualFiles) {
- if (canonicalize(virtualFile.getPath()).equals(rootPath)) {
- return true;
- }
+ return true;
}
return false;
}
- private static String canonicalize(String path) {
- try {
- return new File(path).getCanonicalPath();
+ /**
+ * Removes duplicate roots that have been added as the result of a bug with *.egg handling.
+ */
+ private static boolean removeDuplicateClassRoots(@NotNull Sdk sdk, @NotNull SdkModificator modificator) {
+ final List<VirtualFile> sourceRoots = Arrays.asList(sdk.getRootProvider().getFiles(OrderRootType.CLASSES));
+ final LinkedHashSet<VirtualFile> uniqueRoots = new LinkedHashSet<VirtualFile>(sourceRoots);
+ if (uniqueRoots.size() != sourceRoots.size()) {
+ modificator.removeRoots(OrderRootType.CLASSES);
+ for (VirtualFile root : uniqueRoots) {
+ modificator.addRoot(root, OrderRootType.CLASSES);
+ }
+ return true;
}
- catch (IOException e) {
- return path;
+ return false;
+ }
+
+ /**
+ * Removes legacy SOURCES entries in Python SDK tables (PY-2891).
+ */
+ private static boolean removeSourceRoots(@NotNull Sdk sdk, @NotNull SdkModificator modificator) {
+ final VirtualFile[] sourceRoots = sdk.getRootProvider().getFiles(OrderRootType.SOURCES);
+ if (sourceRoots.length > 0) {
+ modificator.removeRoots(OrderRootType.SOURCES);
+ return true;
}
+ return false;
+ }
+
+ private static boolean wasOldRoot(@NotNull String root, @NotNull Collection<VirtualFile> oldRoots) {
+ final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(root);
+ if (file != null) {
+ final VirtualFile rootFile = PythonSdkType.getSdkRootVirtualFile(file);
+ return oldRoots.contains(rootFile);
+ }
+ return false;
}
}
diff --git a/python/src/com/jetbrains/python/sdk/flavors/MacPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/MacPythonSdkFlavor.java
index 5d241b6..72c8f42 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/MacPythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/MacPythonSdkFlavor.java
@@ -15,14 +15,14 @@
*/
package com.jetbrains.python.sdk.flavors;
+import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VFileProperty;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
+import com.intellij.util.containers.HashSet;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
+import java.util.Set;
/**
* @author yole
@@ -36,30 +36,35 @@
@Override
public Collection<String> suggestHomePaths() {
- List<String> candidates = new ArrayList<String>();
+ Set<String> candidates = new HashSet<String>();
collectPythonInstallations("/Library/Frameworks/Python.framework/Versions", candidates);
collectPythonInstallations("/System/Library/Frameworks/Python.framework/Versions", candidates);
UnixPythonSdkFlavor.collectUnixPythons("/usr/local/bin", candidates);
return candidates;
}
- private static void collectPythonInstallations(String pythonPath, List<String> candidates) {
+ private static void collectPythonInstallations(String pythonPath, Set<String> candidates) {
VirtualFile rootVDir = LocalFileSystem.getInstance().findFileByPath(pythonPath);
if (rootVDir != null) {
if (rootVDir instanceof NewVirtualFile) {
((NewVirtualFile)rootVDir).markDirty();
}
- rootVDir.refresh(false, false);
+ rootVDir.refresh(true, false);
for (VirtualFile dir : rootVDir.getChildren()) {
- final String dir_name = dir.getName().toLowerCase();
+ final String dirName = dir.getName().toLowerCase();
if (dir.isDirectory()) {
- if ("Current".equals(dir_name) || dir_name.startsWith("2") || dir_name.startsWith("3")) {
+ if ("Current".equals(dirName) || dirName.startsWith("2") || dirName.startsWith("3")) {
final VirtualFile binDir = dir.findChild("bin");
if (binDir != null && binDir.isDirectory()) {
for (String name : POSSIBLE_BINARY_NAMES) {
final VirtualFile child = binDir.findChild(name);
- if (child != null && !child.is(VFileProperty.SYMLINK)) {
- candidates.add(child.getPath());
+ if (child == null) continue;
+ String path = child.getPath();
+ if (FileSystemUtil.isSymLink(path)) {
+ path = FileSystemUtil.resolveSymLink(path);
+ }
+ if (path != null && !candidates.contains(path)) {
+ candidates.add(path);
break;
}
}
diff --git a/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java
index 0ad8329..271afc6 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/PyRemoteSdkFlavor.java
@@ -17,7 +17,7 @@
import com.google.common.collect.Lists;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.remotesdk.RemoteFile;
+import com.intellij.remote.RemoteFile;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
diff --git a/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java
index 2440661..b01424b 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java
@@ -15,14 +15,14 @@
*/
package com.jetbrains.python.sdk.flavors;
+import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VFileProperty;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
+import com.intellij.util.containers.HashSet;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
+import java.util.Set;
/**
* @author yole
@@ -37,12 +37,12 @@
@Override
public Collection<String> suggestHomePaths() {
- List<String> candidates = new ArrayList<String>();
+ Set<String> candidates = new HashSet<String>();
collectUnixPythons("/usr/bin", candidates);
return candidates;
}
- public static void collectUnixPythons(String path, List<String> candidates) {
+ public static void collectUnixPythons(String path, Set<String> candidates) {
VirtualFile rootDir = LocalFileSystem.getInstance().findFileByPath(path);
if (rootDir != null) {
if (rootDir instanceof NewVirtualFile) {
@@ -55,9 +55,13 @@
final String childName = child.getName();
for (String name : NAMES) {
if (childName.startsWith(name)) {
- if (!childName.endsWith("-config") && !childName.startsWith("pythonw") &&
- !childName.endsWith("m") && !child.is(VFileProperty.SYMLINK)) {
- candidates.add(child.getPath());
+ String childPath = child.getPath();
+ if (FileSystemUtil.isSymLink(childPath)) {
+ childPath = FileSystemUtil.resolveSymLink(childPath);
+ }
+ if (childPath != null && !childName.endsWith("-config") && !childName.startsWith("pythonw") && !childName.endsWith("m") &&
+ !candidates.contains(childPath)) {
+ candidates.add(childPath);
}
break;
}
diff --git a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java
index b9de2e2..b9bdf8f 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java
@@ -111,7 +111,7 @@
for (String name : NAMES) {
if (SystemInfo.isWindows) {
if (childName.equals(name)) {
- return child.getPath();
+ return FileUtil.toSystemDependentName(child.getPath());
}
}
else {
diff --git a/python/src/com/jetbrains/python/sdk/flavors/WinPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/WinPythonSdkFlavor.java
index 9de862f..8e75e63 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/WinPythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/WinPythonSdkFlavor.java
@@ -40,7 +40,7 @@
public Collection<String> suggestHomePaths() {
Set<String> candidates = new TreeSet<String>();
findInCandidatePaths(candidates, "python.exe", "jython.bat", "pypy.exe");
- candidates.add(PythonHelpersLocator.getHelpersRoot().getParent());
+ findInstallations(candidates, "python.exe", PythonHelpersLocator.getHelpersRoot().getParent());
return candidates;
}
@@ -66,7 +66,7 @@
}
File f = new File(pathEntry, exeName);
if (f.exists()) {
- candidates.add(FileUtil.toSystemIndependentName(f.getPath()));
+ candidates.add(FileUtil.toSystemDependentName(f.getPath()));
}
}
}
@@ -81,7 +81,7 @@
for (VirtualFile dir : rootVDir.getChildren()) {
if (dir.isDirectory() && dir.getName().toLowerCase().startsWith(dir_prefix)) {
VirtualFile python_exe = dir.findChild(exe_name);
- if (python_exe != null) candidates.add(FileUtil.toSystemIndependentName(python_exe.getPath()));
+ if (python_exe != null) candidates.add(FileUtil.toSystemDependentName(python_exe.getPath()));
}
}
}
diff --git a/python/src/com/jetbrains/python/validation/PyAnnotatingVisitor.java b/python/src/com/jetbrains/python/validation/PyAnnotatingVisitor.java
index 39ab363..8accd98 100644
--- a/python/src/com/jetbrains/python/validation/PyAnnotatingVisitor.java
+++ b/python/src/com/jetbrains/python/validation/PyAnnotatingVisitor.java
@@ -31,10 +31,7 @@
*/
public class PyAnnotatingVisitor implements Annotator {
private static final Logger LOGGER = Logger.getInstance(PyAnnotatingVisitor.class.getName());
-
- private final List<PyAnnotator> myAnnotators = new ArrayList<PyAnnotator>();
-
- private final Class[] ANNOTATOR_CLASSES = new Class[] {
+ private static final Class[] ANNOTATOR_CLASSES = new Class[] {
AssignTargetAnnotator.class,
ParameterListAnnotator.class,
HighlightingAnnotator.class,
@@ -44,10 +41,13 @@
GlobalAnnotator.class,
ImportAnnotator.class,
PyBuiltinAnnotator.class,
- UnsupportedFeatures.class
+ UnsupportedFeatures.class
};
+ private final PyAnnotator[] myAnnotators;
+
public PyAnnotatingVisitor() {
+ final List<PyAnnotator> annotators = new ArrayList<PyAnnotator>();
for (Class cls : ANNOTATOR_CLASSES) {
PyAnnotator annotator;
try {
@@ -61,13 +61,14 @@
LOGGER.error(e);
continue;
}
- myAnnotators.add(annotator);
+ annotators.add(annotator);
}
+ myAnnotators = annotators.toArray(new PyAnnotator[annotators.size()]);
}
public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) {
final PsiFile file = psiElement.getContainingFile();
- for(PyAnnotator annotator: myAnnotators) {
+ for (PyAnnotator annotator : myAnnotators) {
if (file instanceof PyFileImpl && !((PyFileImpl)file).isAcceptedFor(annotator.getClass())) continue;
annotator.annotateElement(psiElement, holder);
}
diff --git a/python/src/com/jetbrains/python/validation/PyBuiltinAnnotator.java b/python/src/com/jetbrains/python/validation/PyBuiltinAnnotator.java
index 417c362..102867f 100644
--- a/python/src/com/jetbrains/python/validation/PyBuiltinAnnotator.java
+++ b/python/src/com/jetbrains/python/validation/PyBuiltinAnnotator.java
@@ -18,67 +18,63 @@
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.Annotation;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.ResolveResult;
-import com.jetbrains.python.highlighting.PyHighlighter;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
+import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
+import com.jetbrains.python.highlighting.PyHighlighter;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
+import org.jetbrains.annotations.NotNull;
/**
* Marks built-in names.
- * User: dcheryasov
- * Date: Jan 10, 2009 12:17:15 PM
+ *
+ * @author dcheryasov
*/
public class PyBuiltinAnnotator extends PyAnnotator {
@Override
public void visitPyReferenceExpression(PyReferenceExpression node) {
final String name = node.getName();
- if (name == null) return;
- boolean highlighted_as_attribute = highlightAsAttribute(node, name);
- if (! highlighted_as_attribute && !node.isQualified()) {
- // things like len()
- ResolveResult[] resolved = node.getReference().multiResolve(false); // constructors, etc may give multiple results...
- if (resolved.length > 0) {
- if (PyBuiltinCache.getInstance(node).hasInBuiltins(resolved[0].getElement())) { // ...but we only care about the default resolution
- Annotation ann;
- PsiElement parent = node.getParent();
- if (parent instanceof PyDecorator) {
- // don't mark the entire decorator, only mark the "@", else we'll conflict with deco annotator
- ann = getHolder().createInfoAnnotation(parent.getFirstChild(), null); // first child is there, or we'd not parse as deco
- }
- else ann = getHolder().createInfoAnnotation(node, null);
- ann.setTextAttributes(PyHighlighter.PY_BUILTIN_NAME);
- }
+ if (name == null) return;
+ final boolean highlightedAsAttribute = highlightAsAttribute(node, name);
+ if (!highlightedAsAttribute && PyBuiltinCache.isInBuiltins(node)) {
+ final Annotation ann;
+ final PsiElement parent = node.getParent();
+ if (parent instanceof PyDecorator) {
+ // don't mark the entire decorator, only mark the "@", else we'll conflict with deco annotator
+ ann = getHolder().createInfoAnnotation(parent.getFirstChild(), null); // first child is there, or we'd not parse as deco
}
+ else {
+ ann = getHolder().createInfoAnnotation(node, null);
+ }
+ ann.setTextAttributes(PyHighlighter.PY_BUILTIN_NAME);
}
}
@Override
public void visitPyTargetExpression(PyTargetExpression node) {
final String name = node.getName();
- if (name == null) return;
- highlightAsAttribute(node, name);
+ if (name != null) {
+ highlightAsAttribute(node, name);
+ }
}
/**
* Try to highlight a node as a class attribute.
+ *
* @param node what to work with
- * @return true iff the node was highlighted.
+ * @return true iff the node was highlighted.
*/
- private boolean highlightAsAttribute(PyQualifiedExpression node, String name) {
- LanguageLevel languageLevel = LanguageLevel.forElement(node);
+ private boolean highlightAsAttribute(@NotNull PyQualifiedExpression node, @NotNull String name) {
+ final LanguageLevel languageLevel = LanguageLevel.forElement(node);
if (PyNames.UnderscoredAttributes.contains(name) || PyNames.getBuiltinMethods(languageLevel).containsKey(name)) {
- // things like __len__
- if (
- node.isQualified() // foo.__len__
- || (PyUtil.getConcealingParent(node) instanceof PyClass) // class Foo: ... __len__ = myLenImpl
- ) {
+ // things like __len__: foo.__len__ or class Foo: ... __len__ = my_len_impl
+ if (node.isQualified() || ScopeUtil.getScopeOwner(node) instanceof PyClass) {
final ASTNode astNode = node.getNode();
if (astNode != null) {
- ASTNode tgt = astNode.findChildByType(PyTokenTypes.IDENTIFIER); // only the id, not all qualifiers subtree
+ final ASTNode tgt = astNode.findChildByType(PyTokenTypes.IDENTIFIER); // only the id, not all qualifiers subtree
if (tgt != null) {
- Annotation ann = getHolder().createInfoAnnotation(tgt, null);
+ final Annotation ann = getHolder().createInfoAnnotation(tgt, null);
ann.setTextAttributes(PyHighlighter.PY_PREDEFINED_USAGE);
return true;
}
@@ -87,5 +83,4 @@
}
return false;
}
-
}
diff --git a/python/src/icons/PythonIcons.java b/python/src/icons/PythonIcons.java
index 2adb29d..4e91858 100644
--- a/python/src/icons/PythonIcons.java
+++ b/python/src/icons/PythonIcons.java
@@ -49,7 +49,6 @@
public static final Icon Python_24 = load("/icons/com/jetbrains/python/python_24.png"); // 24x24
public static final Icon PythonClosed = load("/icons/com/jetbrains/python/pythonClosed.png"); // 16x16
public static final Icon PythonTests = load("/icons/com/jetbrains/python/pythonTests.png"); // 16x16
- public static final Icon Skeleton = load("/icons/com/jetbrains/python/skeleton.png"); // 16x16
public static final Icon TemplateRoot = load("/icons/com/jetbrains/python/templateRoot.png"); // 16x16
public static final Icon Virtualenv = load("/icons/com/jetbrains/python/virtualenv.png"); // 16x16
diff --git a/python/testData/refactoring/extractsuperclass/properties.after.py b/python/testData/refactoring/extractsuperclass/properties.after.py
new file mode 100644
index 0000000..e512d94
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/properties.after.py
@@ -0,0 +1,27 @@
+class ToClass(object):
+ C = 12
+
+ def __init__(self):
+ self.a = 1
+
+ def _get(self):
+ return 1
+
+ def _set(self, value):
+ pass
+
+ def _delete(self):
+ pass
+
+ old_property = property(_get, _set, _delete)
+
+ def foo(self):
+ pass
+
+
+class FromClass(ToClass):
+ def __init__(self): pass
+
+
+ def lala(self):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/properties.before.py b/python/testData/refactoring/extractsuperclass/properties.before.py
new file mode 100644
index 0000000..3df31fe
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/properties.before.py
@@ -0,0 +1,22 @@
+class FromClass(object):
+ C = 12
+
+ def __init__(self):
+ self.a = 1
+
+ def _get(self):
+ return 1
+
+ def _set(self, value):
+ pass
+
+ def _delete(self):
+ pass
+
+ old_property = property(_get, _set, _delete)
+
+ def foo(self):
+ pass
+
+ def lala(self):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/presenter/file.py b/python/testData/refactoring/pullup/presenter/file.py
index cb6ca95..f70f47e 100644
--- a/python/testData/refactoring/pullup/presenter/file.py
+++ b/python/testData/refactoring/pullup/presenter/file.py
@@ -30,14 +30,38 @@
pass
class HugeChild(SubParent1, date): #SubParent1 is disabled
+ __metaclass__ = None # Anyway, this field should be ignored and processed separately as "metaclass", not "class field"
+
def __init__(self):
self.instance_field_1 = 42
self.instance_field_2 = 100500
CLASS_FIELD = 42
(CLASS_FIELD_A,CLASS_FIELD_B) = (42,100500) #We do not support tuples in class assignments for now (see ClassFieldsManager)
- def foo(self): #should be disabled
+
+ def _set(self, val): # Should not be treated as method (part of property)
pass
+
+ def _get(self): # Should not be treated as method (part of property)
+ return None
+
+ name = property(fget=_get, fset=_set)
+
+
+ @property
+ def some_property(self): # Should not be treated as method (part of property)
+ return None
+
+ @some_property.setter
+ def some_property(self, val): # Should not be treated as method (part of property)
+ pass
+
+
+
+
+
+ def foo(self): #should be disabled
+ self.some_property = 12
def bar(self):
pass
diff --git a/python/testData/refactoring/pullup/properties/Class.after.py b/python/testData/refactoring/pullup/properties/Class.after.py
new file mode 100644
index 0000000..1291238
--- /dev/null
+++ b/python/testData/refactoring/pullup/properties/Class.after.py
@@ -0,0 +1,19 @@
+from SuperClass import SuperClass
+
+
+class AnyClass(SuperClass):
+ C = 1
+
+ def __init__(self):
+ super(AnyClass, self).__init__()
+
+
+
+
+
+
+
+
+ def foo(self):
+ pass
+
diff --git a/python/testData/refactoring/pullup/properties/Class.py b/python/testData/refactoring/pullup/properties/Class.py
new file mode 100644
index 0000000..5a091a9
--- /dev/null
+++ b/python/testData/refactoring/pullup/properties/Class.py
@@ -0,0 +1,25 @@
+from SuperClass import SuperClass
+
+
+class AnyClass(SuperClass):
+ C = 1
+
+ def __init__(self):
+ super(AnyClass, self).__init__()
+
+
+ @property
+ def new_property(self):
+ return 1
+
+ @new_property.setter
+ def new_property(self, value):
+ pass
+
+ @new_property.deleter
+ def new_property(self):
+ pass
+
+ def foo(self):
+ pass
+
diff --git a/python/testData/refactoring/pullup/properties/SuperClass.after.py b/python/testData/refactoring/pullup/properties/SuperClass.after.py
new file mode 100644
index 0000000..1b2be8d
--- /dev/null
+++ b/python/testData/refactoring/pullup/properties/SuperClass.after.py
@@ -0,0 +1,15 @@
+class SuperClass(object):
+ def __init__(self):
+ pass
+
+ @property
+ def new_property(self):
+ return 1
+
+ @new_property.setter
+ def new_property(self, value):
+ pass
+
+ @new_property.deleter
+ def new_property(self):
+ pass
diff --git a/python/testData/refactoring/pullup/properties/SuperClass.py b/python/testData/refactoring/pullup/properties/SuperClass.py
new file mode 100644
index 0000000..a41b8fd
--- /dev/null
+++ b/python/testData/refactoring/pullup/properties/SuperClass.py
@@ -0,0 +1,3 @@
+class SuperClass(object):
+ def __init__(self):
+ pass
diff --git a/python/testData/refactoring/pullup/pyPullUpInfoModel.py b/python/testData/refactoring/pullup/pyPullUpInfoModel.py
index 04f6430..2f89133 100644
--- a/python/testData/refactoring/pullup/pyPullUpInfoModel.py
+++ b/python/testData/refactoring/pullup/pyPullUpInfoModel.py
@@ -15,12 +15,45 @@
CLASS_FIELD_DEPENDS_ON_CLASS_FIELD_FOO = CLASS_FIELD_FOO
CLASS_FIELD_DEPENDS_ON_PARENT_FIELD = SomeParent.PARENT_CLASS_FIELD
+
def __init__(self):
SomeParent.__init__(self)
self.instance_field_bar = 42
self.depends_on_instance_field_bar = self.instance_field_bar
self.depends_on_class_field_foo = ChildWithDependencies.CLASS_FIELD_FOO
+
+ @property
+ def new_property(self):
+ return 1
+
+ def _set_prop(self, val):
+ pass
+
+ def _get_prop(self):
+ return 1
+
+ def _del_prop(self):
+ pass
+
+ old_property = property(fset=_set_prop)
+ old_property_2 = property(fget=_get_prop)
+ old_property_3 = property(fdel=_del_prop)
+
+
+ @property
+ def new_property(self):
+ return 1
+
+ @new_property.setter
+ def new_property(self, val):
+ pass
+
+ @property
+ def new_property_2(self):
+ return 1
+
+
def normal_method(self):
pass
@@ -36,4 +69,14 @@
self.normal_method()
def method_depends_on_instance_field_bar(self):
- eggs = self.instance_field_bar
\ No newline at end of file
+ eggs = self.instance_field_bar
+
+ def method_depends_on_old_property(self):
+ i = 12
+ self.old_property = i
+ q = self.old_property_2
+ del self.old_property_3
+
+ def method_depends_on_new_property(self):
+ self.new_property = 12
+ print(self.new_property_2)
diff --git a/python/testSrc/com/jetbrains/python/PyEncodingTest.java b/python/testSrc/com/jetbrains/python/PyEncodingTest.java
index cccd6d4..608b839 100644
--- a/python/testSrc/com/jetbrains/python/PyEncodingTest.java
+++ b/python/testSrc/com/jetbrains/python/PyEncodingTest.java
@@ -15,12 +15,12 @@
*/
package com.jetbrains.python;
-import junit.framework.TestCase;
+import com.jetbrains.python.fixtures.PyTestCase;
/**
* @author yole
*/
-public class PyEncodingTest extends TestCase {
+public class PyEncodingTest extends PyTestCase {
public void testEncodingEmacs() {
doTest("#!/usr/bin/python\n# -*- coding: iso-8859-15 -*-\nimport os, sys", "iso-8859-15");
}
@@ -33,7 +33,8 @@
doTest("#!/usr/local/bin/python\n# coding: latin-1\nimport os, sys", "iso-8859-1");
}
- private static void doTest(final String text, final String expected) {
- assertEquals(expected, PythonFileType.getCharsetFromEncodingDeclaration(text));
+ private void doTest(final String text, final String expected) {
+ myFixture.configureByText(PythonFileType.INSTANCE, text);
+ assertEquals(expected, PythonFileType.getCharsetFromEncodingDeclaration(myFixture.getFile()));
}
}
diff --git a/python/testSrc/com/jetbrains/python/PyTypeParserTest.java b/python/testSrc/com/jetbrains/python/PyTypeParserTest.java
index 30dc434..7db230a 100644
--- a/python/testSrc/com/jetbrains/python/PyTypeParserTest.java
+++ b/python/testSrc/com/jetbrains/python/PyTypeParserTest.java
@@ -252,7 +252,7 @@
final PyCallableType callableType = (PyCallableType)type;
assertNotNull(callableType);
final TypeEvalContext context = getTypeEvalContext();
- final PyType returnType = callableType.getCallType(context, null);
+ final PyType returnType = callableType.getReturnType(context);
assertInstanceOf(returnType, PyGenericType.class);
final List<PyCallableParameter> parameterTypes = callableType.getParameters(context);
assertNotNull(parameterTypes);
@@ -271,7 +271,7 @@
assertInstanceOf(type, PyCallableType.class);
final PyCallableType callableType = (PyCallableType)type;
assertNotNull(callableType);
- final PyType returnType = callableType.getCallType(getTypeEvalContext(), null);
+ final PyType returnType = callableType.getReturnType(getTypeEvalContext());
assertNotNull(returnType);
assertEquals("int", returnType.getName());
final List<PyCallableParameter> parameterTypes = callableType.getParameters(getTypeEvalContext());
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java
index 13d5b4d..c96bdc2 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java
@@ -125,6 +125,11 @@
doSimpleTest("FromClass", "ToClass", null, true, "#instance_field", "#CLASS_FIELD");
}
+
+ public void testProperties() throws Exception {
+ doSimpleTest("FromClass", "ToClass", null, true, "#C", "#a", "._get", ".foo");
+ }
+
private void doSimpleTest(final String className,
final String superclassName,
final String expectedError,
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpInfoModelTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpInfoModelTest.java
index 9fe02c3..3e5e508 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpInfoModelTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpInfoModelTest.java
@@ -69,6 +69,27 @@
Assert.assertThat("Instance on member dependencies failed", getErrorMemberNames(), Matchers.containsInAnyOrder("self.instance_field_bar"));
}
+ /**
+ * Check dependnecies for properties, declared in old-style
+ *
+ */
+ public void testOldProperty() throws Exception {
+ checkMembers("method_depends_on_old_property(self)");
+ Assert.assertThat("Method on old property dependency failed", getErrorMemberNames(), Matchers.containsInAnyOrder(
+ "old_property",
+ "old_property_2",
+ "old_property_3"));
+ }
+
+ /**
+ *
+ * Check dependnecies for properties, declared in new-style
+ */
+ public void testNewProperty() throws Exception {
+ checkMembers("method_depends_on_new_property(self)");
+ Assert.assertThat("Method on new property dependency failed", getErrorMemberNames(), Matchers.containsInAnyOrder("new_property", "new_property_2"));
+ }
+
/**
* All dependencies are met: new (destination) class has all of them
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java
index ee5371c..1ee20d2 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java
@@ -144,7 +144,9 @@
new PyPresenterTestMemberEntry("static_2()", true, true, py3K),
new PyPresenterTestMemberEntry("self.instance_field_1", true, false, false),
new PyPresenterTestMemberEntry("self.instance_field_2", true, false, false),
- new PyPresenterTestMemberEntry("bad_method()", true, false, true));
+ new PyPresenterTestMemberEntry("bad_method()", true, false, true),
+ new PyPresenterTestMemberEntry("name", true, false, false),
+ new PyPresenterTestMemberEntry("some_property", true, false, false));
compareMembers(memberNamesAndStatus, matcher);
}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpTest.java
index d725c17..fbf5688 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpTest.java
@@ -97,6 +97,13 @@
doMultiFileTest();
}
+ public void testProperties() {
+ final String[] modules = {"Class", "SuperClass"};
+ configureMultiFile(modules);
+ doPullUp("AnyClass", "SuperClass", ".new_property");
+ checkMultiFile(modules);
+ }
+
public void testFieldMove() {
final String[] modules = {"Class", "SuperClass"};
configureMultiFile(modules);