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/.idea/libraries/Netty.xml b/.idea/libraries/Netty.xml
index 8037545..bc6600b 100644
--- a/.idea/libraries/Netty.xml
+++ b/.idea/libraries/Netty.xml
@@ -1,11 +1,11 @@
 <component name="libraryTable">
   <library name="Netty">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/lib/netty-all-5.0.0.Alpha1.jar!/" />
+      <root url="jar://$PROJECT_DIR$/lib/netty-all-5.0.0.Alpha2.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$PROJECT_DIR$/lib/src/netty-all-5.0.0.Alpha1-sources.jar!/" />
+      <root url="jar://$PROJECT_DIR$/lib/src/netty-all-5.0.0.Alpha2-sources.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index d7c5d4a..2c0aba5 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -98,6 +98,8 @@
       <module fileurl="file://$PROJECT_DIR$/jps/model-api/jps-model-api.iml" filepath="$PROJECT_DIR$/jps/model-api/jps-model-api.iml" group="jps" />
       <module fileurl="file://$PROJECT_DIR$/jps/model-impl/jps-model-impl.iml" filepath="$PROJECT_DIR$/jps/model-impl/jps-model-impl.iml" group="jps" />
       <module fileurl="file://$PROJECT_DIR$/jps/model-serialization/jps-model-serialization.iml" filepath="$PROJECT_DIR$/jps/model-serialization/jps-model-serialization.iml" group="jps" />
+      <module fileurl="file://$PROJECT_DIR$/jps/model-impl/jps-model-tests.iml" filepath="$PROJECT_DIR$/jps/model-impl/jps-model-tests.iml"/>
+      <module fileurl="file://$PROJECT_DIR$/jps/model-serialization/jps-serialization-tests.iml" filepath="$PROJECT_DIR$/jps/model-serialization/jps-serialization-tests.iml" group="jps"/>
       <module fileurl="file://$PROJECT_DIR$/jps/standalone-builder/jps-standalone-builder.iml" filepath="$PROJECT_DIR$/jps/standalone-builder/jps-standalone-builder.iml" group="jps" />
       <module fileurl="file://$PROJECT_DIR$/java/jsp-base-openapi/jsp-base-openapi.iml" filepath="$PROJECT_DIR$/java/jsp-base-openapi/jsp-base-openapi.iml" group="java" />
       <module fileurl="file://$PROJECT_DIR$/java/jsp-openapi/jsp-openapi.iml" filepath="$PROJECT_DIR$/java/jsp-openapi/jsp-openapi.iml" group="java" />
diff --git a/bin/win/runnerw.exe b/bin/win/runnerw.exe
index affd133..5c5f103 100644
--- a/bin/win/runnerw.exe
+++ b/bin/win/runnerw.exe
Binary files differ
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index 8a9c8d0..c36ccf8 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -250,7 +250,7 @@
   }
 
   dir("plugins") {
-    def simplePlugins = ["commander", "copyright", "java-i18n", "hg4idea", "github", "ui-designer-core"] //, "tasks-time-tracking"]
+    def simplePlugins = ["commander", "copyright", "java-i18n", "hg4idea", "github"] //, "tasks-time-tracking"]
 
     simplePlugins.each {
       layoutPlugin it
@@ -678,9 +678,19 @@
       }
     }
 
-    layoutPlugin("android-designer") {
-      jar("android-designer.jar") {
-        module("android-designer")
+    dir("android-designer") {
+      dir("lib") {
+        jar("resources_en.jar") {
+          module("ui-designer-core") {
+            patternset(refid: "resources.included")
+          }
+        }
+        jar("android-designer.jar") {
+          module("ui-designer-core") {
+            patternset(refid: "resources.excluded")
+          }
+          module("android-designer")
+        }
       }
     }
   }
@@ -749,8 +759,8 @@
     dir("test") {
       jar("jps-build-test.jar") {
         moduleTests("jps-builders")
-        moduleTests("jps-model-impl")
-        moduleTests("jps-model-serialization")
+        moduleTests("jps-model-tests")
+        moduleTests("jps-serialization-tests")
       }
     }
     jar("ant-jps-plugin.jar") { module("ant-jps-plugin") }
diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant
index b52405e..8065038 100644
--- a/build/scripts/utils.gant
+++ b/build/scripts/utils.gant
@@ -353,7 +353,7 @@
   String archs = """
     <key>LSArchitecturePriority</key>
     <array>"""
-  (args.archs != null ? args.archs : ["64_x86", "i386"]).each {
+  (args.archs != null ? args.archs : ["x86_64", "i386"]).each {
     archs += "<string>${it}</string>"
   }
   archs +="</array>\n"
diff --git a/community-main.iml b/community-main.iml
index 6e14389..474b93d 100644
--- a/community-main.iml
+++ b/community-main.iml
@@ -93,6 +93,9 @@
     <orderEntry type="module" module-name="manifest" />
     <orderEntry type="module" module-name="xml-tests" scope="TEST" />
     <orderEntry type="module" module-name="devkit-jps-plugin" scope="TEST" />
+    <orderEntry type="module" module-name="jps-model-tests" scope="TEST" />
+    <orderEntry type="module" module-name="jps-serialization-tests" scope="TEST" />
+    <orderEntry type="module" module-name="ui-designer-jps-plugin" scope="TEST" />
     <orderEntry type="module" module-name="ui-designer-jps-plugin" scope="TEST" />
     <orderEntry type="module" module-name="java-tests" scope="TEST" />
     <orderEntry type="module" module-name="community-tests" scope="TEST" />
diff --git a/community-resources/src/idea_community_about.png b/community-resources/src/idea_community_about.png
index 871356c..2b5a763 100644
--- a/community-resources/src/idea_community_about.png
+++ b/community-resources/src/idea_community_about.png
Binary files differ
diff --git a/community-resources/src/idea_community_about@2x.png b/community-resources/src/idea_community_about@2x.png
index caf2a35..f159fb0 100644
--- a/community-resources/src/idea_community_about@2x.png
+++ b/community-resources/src/idea_community_about@2x.png
Binary files differ
diff --git a/community-resources/src/idea_community_logo.png b/community-resources/src/idea_community_logo.png
index 057bb16..91a8153 100644
--- a/community-resources/src/idea_community_logo.png
+++ b/community-resources/src/idea_community_logo.png
Binary files differ
diff --git a/community-resources/src/idea_community_logo@2x.png b/community-resources/src/idea_community_logo@2x.png
index 451e5f2..1f2cfb1 100644
--- a/community-resources/src/idea_community_logo@2x.png
+++ b/community-resources/src/idea_community_logo@2x.png
Binary files differ
diff --git a/images/src/org/intellij/images/index/ImageInfoIndex.java b/images/src/org/intellij/images/index/ImageInfoIndex.java
index 28838b5..f2db1b4 100644
--- a/images/src/org/intellij/images/index/ImageInfoIndex.java
+++ b/images/src/org/intellij/images/index/ImageInfoIndex.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.
@@ -46,14 +46,14 @@
 
   private final DataExternalizer<ImageInfo> myValueExternalizer = new DataExternalizer<ImageInfo>() {
     @Override
-    public void save(final DataOutput out, final ImageInfo info) throws IOException {
+    public void save(@NotNull final DataOutput out, final ImageInfo info) throws IOException {
       DataInputOutputUtil.writeINT(out, info.width);
       DataInputOutputUtil.writeINT(out, info.height);
       DataInputOutputUtil.writeINT(out, info.bpp);
     }
 
     @Override
-    public ImageInfo read(final DataInput in) throws IOException {
+    public ImageInfo read(@NotNull final DataInput in) throws IOException {
       return new ImageInfo(DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in));
     }
   };
@@ -83,16 +83,18 @@
         .fileScope(project, virtualFile));
   }
 
+  @NotNull
   @Override
   public DataExternalizer<ImageInfo> getValueExternalizer() {
     return myValueExternalizer;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return new DefaultFileTypeSpecificInputFilter(ImageFileTypeManager.getInstance().getImageFileType()) {
       @Override
-      public boolean acceptInput(final VirtualFile file) {
+      public boolean acceptInput(@NotNull final VirtualFile file) {
         return file.isInLocalFileSystem() &&
                file.getLength() / 1024 < ourMaxImageSize
           ;
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/StateCache.java b/java/compiler/impl/src/com/intellij/compiler/impl/StateCache.java
index bd56b66..631988e 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/StateCache.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/StateCache.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -19,6 +19,7 @@
 import com.intellij.util.io.EnumeratorStringDescriptor;
 import com.intellij.util.io.PersistentHashMap;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -92,11 +93,11 @@
 
   private PersistentHashMap<String, T> createMap(final File file) throws IOException {
     return new PersistentHashMap<String,T>(file, new EnumeratorStringDescriptor(), new DataExternalizer<T>() {
-      public void save(final DataOutput out, final T value) throws IOException {
+      public void save(@NotNull final DataOutput out, final T value) throws IOException {
         StateCache.this.write(value, out);
       }
 
-      public T read(final DataInput in) throws IOException {
+      public T read(@NotNull final DataInput in) throws IOException {
         return StateCache.this.read(in);
       }
     });
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java
index a20c697..411fa24 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java
@@ -80,7 +80,7 @@
  */
 public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
   private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.TranslatingCompilerFilesMonitor");
-  private static final boolean ourDebugMode = false;
+  public static boolean ourDebugMode = false;
 
   private static final FileAttribute ourSourceFileAttribute = new FileAttribute("_make_source_file_info_", 3);
   private static final FileAttribute ourOutputFileAttribute = new FileAttribute("_make_output_file_info_", 3);
@@ -89,7 +89,6 @@
   private final Object myDataLock = new Object();
 
   private final TIntHashSet mySuspendedProjects = new TIntHashSet(); // projectId for all projects that should not be monitored
-  private volatile int myWatchedProjectsCount;
 
   private final TIntObjectHashMap<TIntHashSet> mySourcesToRecompile = new TIntObjectHashMap<TIntHashSet>(); // ProjectId->set of source file paths
   private PersistentHashMap<Integer, TIntObjectHashMap<Pair<Integer, Integer>>> myOutputRootsStorage; // ProjectId->map[moduleId->Pair(outputDirId, testOutputDirId)]
@@ -196,7 +195,6 @@
         return;
       }
       FileUtil.createIfDoesntExist(CompilerPaths.getRebuildMarkerFile(project));
-      --myWatchedProjectsCount;
       // cleanup internal structures to free memory
       mySourcesToRecompile.remove(projectId);
       myOutputsToDelete.remove(projectId);
@@ -217,8 +215,8 @@
 
   public void watchProject(Project project) {
     synchronized (myDataLock) {
-      mySuspendedProjects.remove(getProjectId(project));
-      ++myWatchedProjectsCount;
+      int projectId = getProjectId(project);
+      mySuspendedProjects.remove(projectId);
     }
   }
 
@@ -600,7 +598,7 @@
 
   private void initOutputRootsFile(File rootsFile) throws IOException {
     myOutputRootsStorage = new PersistentHashMap<Integer, TIntObjectHashMap<Pair<Integer, Integer>>>(rootsFile, EnumeratorIntegerDescriptor.INSTANCE, new DataExternalizer<TIntObjectHashMap<Pair<Integer, Integer>>>() {
-      public void save(DataOutput out, TIntObjectHashMap<Pair<Integer, Integer>> value) throws IOException {
+      public void save(@NotNull DataOutput out, TIntObjectHashMap<Pair<Integer, Integer>> value) throws IOException {
         for (final TIntObjectIterator<Pair<Integer, Integer>> it = value.iterator(); it.hasNext();) {
           it.advance();
           DataInputOutputUtil.writeINT(out, it.key());
@@ -610,7 +608,7 @@
         }
       }
 
-      public TIntObjectHashMap<Pair<Integer, Integer>> read(DataInput in) throws IOException {
+      public TIntObjectHashMap<Pair<Integer, Integer>> read(@NotNull DataInput in) throws IOException {
         final DataInputStream _in = (DataInputStream)in;
         final TIntObjectHashMap<Pair<Integer, Integer>> map = new TIntObjectHashMap<Pair<Integer, Integer>>();
         while (_in.available() > 0) {
@@ -1476,7 +1474,6 @@
     }
 
     public void beforeFileDeletion(@NotNull final VirtualFileEvent event) {
-      if (myWatchedProjectsCount == 0) return;
       final VirtualFile eventFile = event.getFile();
       if ((LOG.isDebugEnabled() && eventFile.isDirectory()) || ourDebugMode) {
         final String message = "Processing file deletion: " + eventFile.getPresentableUrl();
@@ -1616,7 +1613,6 @@
     }
 
     private void processNewFile(final VirtualFile file, final boolean notifyServer) {
-      if (myWatchedProjectsCount == 0) return;
       final Ref<Boolean> isInContent = Ref.create(false);
       ApplicationManager.getApplication().runReadAction(new Runnable() {
         // need read action to ensure that the project was not disposed during the iteration over the project list
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/generic/GenericCompilerCache.java b/java/compiler/impl/src/com/intellij/compiler/impl/generic/GenericCompilerCache.java
index 5741b9c..4db8786 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/generic/GenericCompilerCache.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/generic/GenericCompilerCache.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -112,8 +112,8 @@
   }
 
   public static class PersistentStateData<SourceState, OutputState> {
-    public final SourceState mySourceState;
-    public final OutputState myOutputState;
+    @NotNull public final SourceState mySourceState;
+    @NotNull public final OutputState myOutputState;
 
     private PersistentStateData(@NotNull SourceState sourceState, @NotNull OutputState outputState) {
       mySourceState = sourceState;
@@ -139,14 +139,14 @@
     }
 
     @Override
-    public void save(DataOutput out, KeyAndTargetData<Key> value) throws IOException {
+    public void save(@NotNull DataOutput out, KeyAndTargetData<Key> value) throws IOException {
       out.writeInt(value.myTarget);
       myKeyDescriptor.save(out, value.myKey);
     }
 
 
     @Override
-    public KeyAndTargetData<Key> read(DataInput in) throws IOException {
+    public KeyAndTargetData<Key> read(@NotNull DataInput in) throws IOException {
       int target = in.readInt();
       final Key item = myKeyDescriptor.read(in);
       return getKeyAndTargetData(item, target);
@@ -163,13 +163,13 @@
     }
 
     @Override
-    public void save(DataOutput out, PersistentStateData<SourceState, OutputState> value) throws IOException {
+    public void save(@NotNull DataOutput out, PersistentStateData<SourceState, OutputState> value) throws IOException {
       mySourceStateExternalizer.save(out, value.mySourceState);
       myOutputStateExternalizer.save(out, value.myOutputState);
     }
 
     @Override
-    public PersistentStateData<SourceState, OutputState> read(DataInput in) throws IOException {
+    public PersistentStateData<SourceState, OutputState> read(@NotNull DataInput in) throws IOException {
       SourceState sourceState = mySourceStateExternalizer.read(in);
       OutputState outputState = myOutputStateExternalizer.read(in);
       return new PersistentStateData<SourceState,OutputState>(sourceState, outputState);
diff --git a/java/compiler/impl/src/com/intellij/compiler/make/BackwardDependenciesStorage.java b/java/compiler/impl/src/com/intellij/compiler/make/BackwardDependenciesStorage.java
index fb7a5c6..006debb 100644
--- a/java/compiler/impl/src/com/intellij/compiler/make/BackwardDependenciesStorage.java
+++ b/java/compiler/impl/src/com/intellij/compiler/make/BackwardDependenciesStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -357,7 +357,7 @@
   }
 
   private static class MyDataExternalizer implements DataExternalizer<DependenciesSet> {
-    public void save(DataOutput out, DependenciesSet ds) throws IOException {
+    public void save(@NotNull DataOutput out, DependenciesSet ds) throws IOException {
       final TIntHashSet classes = new TIntHashSet();
       final Map<Dependency.FieldRef, TIntHashSet> fieldsMap = new HashMap<Dependency.FieldRef, TIntHashSet>();
       final Map<Dependency.MethodRef, TIntHashSet> methodsMap = new HashMap<Dependency.MethodRef, TIntHashSet>();
@@ -414,7 +414,7 @@
       }
     }
 
-    public DependenciesSet read(DataInput in) throws IOException {
+    public DependenciesSet read(@NotNull DataInput in) throws IOException {
       final Set<ReferencerItem> set = new THashSet<ReferencerItem>();
 
       int classesCount = in.readInt();
diff --git a/java/compiler/impl/src/com/intellij/compiler/make/Cache.java b/java/compiler/impl/src/com/intellij/compiler/make/Cache.java
index 2e3d554..f80cb8e 100644
--- a/java/compiler/impl/src/com/intellij/compiler/make/Cache.java
+++ b/java/compiler/impl/src/com/intellij/compiler/make/Cache.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -25,6 +25,7 @@
 import com.intellij.util.io.EnumeratorIntegerDescriptor;
 import com.intellij.util.io.PersistentHashMap;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.DataInput;
@@ -54,10 +55,10 @@
     myStorePath = storePath;
     new File(storePath).mkdirs();
     myQNameToClassInfoMap = new CachedPersistentHashMap<Integer, ClassInfo>(getOrCreateFile("classes"), EnumeratorIntegerDescriptor.INSTANCE, new DataExternalizer<ClassInfo>() {
-      public void save(DataOutput out, ClassInfo value) throws IOException {
+      public void save(@NotNull DataOutput out, ClassInfo value) throws IOException {
         value.save(out);
       }
-      public ClassInfo read(DataInput in) throws IOException {
+      public ClassInfo read(@NotNull DataInput in) throws IOException {
         return new ClassInfo(in);
       }
     }, cacheSize * 2) {
@@ -71,11 +72,11 @@
     myQNameToSubclassesMap = new CompilerDependencyStorage<Integer>(getOrCreateFile("subclasses"), EnumeratorIntegerDescriptor.INSTANCE, cacheSize);
 
     myRemoteQNames = new PersistentHashMap<Integer, Boolean>(getOrCreateFile("remote"), EnumeratorIntegerDescriptor.INSTANCE, new DataExternalizer<Boolean>() {
-      public void save(DataOutput out, Boolean value) throws IOException {
+      public void save(@NotNull DataOutput out, Boolean value) throws IOException {
         out.writeBoolean(value.booleanValue());
       }
 
-      public Boolean read(DataInput in) throws IOException {
+      public Boolean read(@NotNull DataInput in) throws IOException {
         return in.readBoolean();
       }
     }, cacheSize);
diff --git a/java/compiler/impl/src/com/intellij/compiler/make/CompilerDependencyStorage.java b/java/compiler/impl/src/com/intellij/compiler/make/CompilerDependencyStorage.java
index ea93f21..2466881 100644
--- a/java/compiler/impl/src/com/intellij/compiler/make/CompilerDependencyStorage.java
+++ b/java/compiler/impl/src/com/intellij/compiler/make/CompilerDependencyStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -40,14 +40,14 @@
 
   public CompilerDependencyStorage(File file, KeyDescriptor<Key> keyDescriptor, final int cacheSize) throws IOException {
     myMap = new PersistentHashMap<Key, int[]>(file, keyDescriptor, new DataExternalizer<int[]>() {
-      public void save(DataOutput out, int[] array) throws IOException {
+      public void save(@NotNull DataOutput out, int[] array) throws IOException {
         out.writeInt(array.length);
         for (int value : array) {
           out.writeInt(value);
         }
       }
 
-      public int[] read(DataInput in) throws IOException {
+      public int[] read(@NotNull DataInput in) throws IOException {
         final TIntHashSet set = new TIntHashSet();
         DataInputStream stream = (DataInputStream)in;
         while(stream.available() > 0) {
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
index 13d9be0..506580c 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
@@ -928,6 +928,7 @@
     launcherCp.add(ClasspathBootstrap.getResourcePath(launcherClass));
     launcherCp.add(compilerPath);
     ClasspathBootstrap.appendJavaCompilerClasspath(launcherCp);
+    launcherCp.addAll(BuildProcessClasspathManager.getLauncherClasspath(project));
     cmdLine.addParameter("-classpath");
     cmdLine.addParameter(classpathToString(launcherCp));
     
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildProcessParametersProvider.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildProcessParametersProvider.java
index 434633f..1da1b5c 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildProcessParametersProvider.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildProcessParametersProvider.java
@@ -27,10 +27,23 @@
 public abstract class BuildProcessParametersProvider {
   public static final ExtensionPointName<BuildProcessParametersProvider> EP_NAME = ExtensionPointName.create("com.intellij.buildProcess.parametersProvider");
 
+  /**
+   * Override this method to include additional jars to the build process classpath
+   * @return list of paths to additional jars to be included to the build process classpath
+   */
   public @NotNull List<String> getClassPath() {
     return Collections.emptyList();
   }
-  
+
+  /**
+   * Override this method to include additional jars to the build process launcher classpath. This may be needed if the plugin provides
+   * custom implementation of Java compiler which must be loaded by the same classloader as tools.jar
+   * @return list of paths to additional jars to be included to the build process launcher classpath
+   */
+  public @NotNull List<String> getLauncherClassPath() {
+    return Collections.emptyList();
+  }
+
   public @NotNull List<String> getVMArguments() {
     return Collections.emptyList();
   }
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/impl/BuildProcessClasspathManager.java b/java/compiler/impl/src/com/intellij/compiler/server/impl/BuildProcessClasspathManager.java
index 2c06c2f..5cef06d 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/impl/BuildProcessClasspathManager.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/impl/BuildProcessClasspathManager.java
@@ -141,4 +141,12 @@
     }
     return classpath;
   }
+
+  public static List<String> getLauncherClasspath(Project project) {
+    final List<String> classpath = ContainerUtil.newArrayList();
+    for (BuildProcessParametersProvider provider : project.getExtensions(BuildProcessParametersProvider.EP_NAME)) {
+      classpath.addAll(provider.getLauncherClassPath());
+    }
+    return classpath;
+  }
 }
diff --git a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/DummyPersistentState.java b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/DummyPersistentState.java
index b3d66ce..495b5a0 100644
--- a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/DummyPersistentState.java
+++ b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/DummyPersistentState.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -16,6 +16,7 @@
 package com.intellij.openapi.compiler.generic;
 
 import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -33,11 +34,11 @@
 
   private static class DummyPersistentStateExternalizer implements DataExternalizer<DummyPersistentState> {
     @Override
-    public void save(DataOutput out, DummyPersistentState value) throws IOException {
+    public void save(@NotNull DataOutput out, DummyPersistentState value) throws IOException {
     }
 
     @Override
-    public DummyPersistentState read(DataInput in) throws IOException {
+    public DummyPersistentState read(@NotNull DataInput in) throws IOException {
       return INSTANCE;
     }
   }
diff --git a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFilePersistentState.java b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFilePersistentState.java
index e9ea970..17739b1 100644
--- a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFilePersistentState.java
+++ b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFilePersistentState.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -16,6 +16,7 @@
 package com.intellij.openapi.compiler.generic;
 
 import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -38,12 +39,12 @@
 
   private static class VirtualFileStateExternalizer implements DataExternalizer<VirtualFilePersistentState> {
     @Override
-    public void save(DataOutput out, VirtualFilePersistentState value) throws IOException {
+    public void save(@NotNull DataOutput out, VirtualFilePersistentState value) throws IOException {
       out.writeLong(value.getSourceTimestamp());
     }
 
     @Override
-    public VirtualFilePersistentState read(DataInput in) throws IOException {
+    public VirtualFilePersistentState read(@NotNull DataInput in) throws IOException {
       return new VirtualFilePersistentState(in.readLong());
     }
 
diff --git a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileSetState.java b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileSetState.java
index a22e80d..cf74b55 100644
--- a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileSetState.java
+++ b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileSetState.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -67,7 +67,7 @@
     private byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
 
     @Override
-    public void save(DataOutput out, VirtualFileSetState value) throws IOException {
+    public void save(@NotNull DataOutput out, VirtualFileSetState value) throws IOException {
       final Map<String, Long> dependencies = value.myTimestamps;
       out.writeInt(dependencies.size());
       for (Map.Entry<String, Long> entry : dependencies.entrySet()) {
@@ -77,7 +77,7 @@
     }
 
     @Override
-    public VirtualFileSetState read(DataInput in) throws IOException {
+    public VirtualFileSetState read(@NotNull DataInput in) throws IOException {
       final VirtualFileSetState state = new VirtualFileSetState();
       int size = in.readInt();
       while (size-- > 0) {
diff --git a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileWithDependenciesState.java b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileWithDependenciesState.java
index 9f4a815..1b9aee4 100644
--- a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileWithDependenciesState.java
+++ b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileWithDependenciesState.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -63,7 +63,7 @@
     private byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
 
     @Override
-    public void save(DataOutput out, VirtualFileWithDependenciesState value) throws IOException {
+    public void save(@NotNull DataOutput out, VirtualFileWithDependenciesState value) throws IOException {
       out.writeLong(value.mySourceTimestamp);
       final Map<String, Long> dependencies = value.myDependencies;
       out.writeInt(dependencies.size());
@@ -74,7 +74,7 @@
     }
 
     @Override
-    public VirtualFileWithDependenciesState read(DataInput in) throws IOException {
+    public VirtualFileWithDependenciesState read(@NotNull DataInput in) throws IOException {
       final VirtualFileWithDependenciesState state = new VirtualFileWithDependenciesState(in.readLong());
       int size = in.readInt();
       while (size-- > 0) {
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactPackagingItemExternalizer.java b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactPackagingItemExternalizer.java
index 030e948..c0a547e 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactPackagingItemExternalizer.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactPackagingItemExternalizer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -19,6 +19,7 @@
 import com.intellij.util.SmartList;
 import com.intellij.util.io.DataExternalizer;
 import com.intellij.util.io.IOUtil;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -31,7 +32,7 @@
   private byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
 
   @Override
-  public void save(DataOutput out, ArtifactPackagingItemOutputState value) throws IOException {
+  public void save(@NotNull DataOutput out, ArtifactPackagingItemOutputState value) throws IOException {
     out.writeInt(value.myDestinations.size());
     for (Pair<String, Long> pair : value.myDestinations) {
       IOUtil.writeUTFFast(myBuffer, out, pair.getFirst());
@@ -40,7 +41,7 @@
   }
 
   @Override
-  public ArtifactPackagingItemOutputState read(DataInput in) throws IOException {
+  public ArtifactPackagingItemOutputState read(@NotNull DataInput in) throws IOException {
     int size = in.readInt();
     SmartList<Pair<String, Long>> destinations = new SmartList<Pair<String, Long>>();
     while (size-- > 0) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/InstanceFilter.java b/java/debugger/impl/src/com/intellij/debugger/InstanceFilter.java
index 9ce095c..09be130 100644
--- a/java/debugger/impl/src/com/intellij/debugger/InstanceFilter.java
+++ b/java/debugger/impl/src/com/intellij/debugger/InstanceFilter.java
@@ -20,6 +20,9 @@
 import com.intellij.openapi.util.JDOMExternalizable;
 import com.intellij.openapi.util.WriteExternalException;
 import com.intellij.ui.classFilter.ClassFilter;
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import com.intellij.util.xmlb.annotations.Transient;
 import org.jdom.Element;
 
 /**
@@ -27,10 +30,13 @@
  * Date: Aug 29, 2003
  * Time: 2:49:27 PM
  */
+@Tag("instance-filter")
 public class InstanceFilter implements JDOMExternalizable{
   public static final InstanceFilter[] EMPTY_ARRAY = new InstanceFilter[0];
-  
+
+  @Attribute("id")
   public long    ID      = 0;
+  @Attribute("enabled")
   public boolean ENABLED = true;
 
   public InstanceFilter() {
@@ -41,10 +47,12 @@
     this.ENABLED = ENABLED;
   }
 
+  @Transient
   public long getId() {
     return ID;
   }
 
+  @Transient
   public boolean isEnabled() {
     return ENABLED;
   }
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java
deleted file mode 100644
index 9ed769a..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.actions;
-
-import com.intellij.debugger.DebuggerManagerEx;
-import com.intellij.debugger.ui.breakpoints.BreakpointFactory;
-import com.intellij.debugger.ui.breakpoints.BreakpointPropertiesPanel;
-import com.intellij.debugger.ui.breakpoints.BreakpointWithHighlighter;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.markup.GutterIconRenderer;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.popup.Balloon;
-import com.intellij.openapi.ui.popup.JBPopupListener;
-import com.intellij.openapi.ui.popup.LightweightWindowEvent;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.wm.IdeFocusManager;
-import com.intellij.util.ui.UIUtil;
-import com.intellij.xdebugger.impl.actions.EditBreakpointActionHandler;
-import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil;
-import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointsDialogFactory;
-import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.awt.*;
-
-public class JavaEditBreakpointActionHandler extends EditBreakpointActionHandler {
-  @Override
-  protected void doShowPopup(final Project project, final JComponent component, final Point whereToShow, final Object breakpoint) {
-    if (!(breakpoint instanceof BreakpointWithHighlighter)) {
-      return;
-    }
-
-    final BreakpointWithHighlighter javaBreakpoint = (BreakpointWithHighlighter)breakpoint;
-    BreakpointFactory breakpointFactory = null;
-    for (BreakpointFactory factory : BreakpointFactory.EXTENSION_POINT_NAME.getExtensions()) {
-      if (factory.getBreakpointCategory().equals(javaBreakpoint.getCategory())) {
-        breakpointFactory = factory;
-      }
-    }
-    assert breakpointFactory != null : "can't find factory for breakpoint " + javaBreakpoint;
-
-    final BreakpointPropertiesPanel propertiesPanel = breakpointFactory.createBreakpointPropertiesPanel(project, true);
-    assert propertiesPanel != null;
-    propertiesPanel.initFrom(javaBreakpoint, false);
-
-    final JComponent mainPanel = propertiesPanel.getPanel();
-    final JBPopupListener saveOnClose = new JBPopupListener.Adapter() {
-      @Override
-      public void onClosed(LightweightWindowEvent event) {
-        propertiesPanel.saveTo(javaBreakpoint);
-        propertiesPanel.dispose();
-        DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().fireBreakpointChanged(javaBreakpoint);
-      }
-    };
-
-    final Runnable showMoreOptions = new Runnable() {
-      @Override
-      public void run() {
-        UIUtil.invokeLaterIfNeeded(new Runnable() {
-          @Override
-          public void run() {
-            BreakpointsDialogFactory.getInstance(project).showDialog(javaBreakpoint);
-          }
-        });
-      }
-    };
-
-    final Balloon balloon = DebuggerUIUtil.showBreakpointEditor(project, mainPanel, whereToShow, component, showMoreOptions, breakpoint);
-    balloon.addListener(saveOnClose);
-
-    propertiesPanel.setDelegate(new BreakpointPropertiesPanel.Delegate() {
-      @Override
-      public void showActionsPanel() {
-        propertiesPanel.setActionsPanelVisible(true);
-        balloon.hide();
-        DebuggerUIUtil.showBreakpointEditor(project, mainPanel, whereToShow, component, showMoreOptions, breakpoint).addListener(saveOnClose);
-      }
-    });
-
-    ApplicationManager.getApplication().invokeLater(new Runnable() {
-      @Override
-      public void run() {
-        IdeFocusManager.findInstance().requestFocus(mainPanel, true);
-      }
-    });
-  }
-
-  @Override
-  public boolean isEnabled(@NotNull Project project, AnActionEvent event) {
-    DataContext dataContext = event.getDataContext();
-    Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
-    if (editor == null) {
-      return false;
-    }
-    final Pair<GutterIconRenderer,Object> pair = XBreakpointUtil.findSelectedBreakpoint(project, editor);
-    return pair.first != null && pair.second instanceof BreakpointWithHighlighter;
-  }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JumpToObjectAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/JumpToObjectAction.java
index 89e32bc..498ee6d 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/JumpToObjectAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/JumpToObjectAction.java
@@ -35,6 +35,7 @@
 
 public class JumpToObjectAction extends DebuggerAction{
   private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.actions.JumpToObjectAction");
+  @Override
   public void actionPerformed(AnActionEvent e) {
     DebuggerTreeNodeImpl selectedNode = getSelectedNode(e.getDataContext());
     if(selectedNode == null) {
@@ -55,6 +56,7 @@
     debugProcess.getManagerThread().schedule(new NavigateCommand(debuggerContext, (ValueDescriptor)descriptor, debugProcess, e));
   }
 
+  @Override
   public void update(final AnActionEvent e) {
     if(!isFirstStart(e)) {
       return;
@@ -82,7 +84,7 @@
     }
   }
 
-  private SourcePosition calcPosition(final ValueDescriptor descriptor, final DebugProcessImpl debugProcess) throws ClassNotLoadedException {
+  private static SourcePosition calcPosition(final ValueDescriptor descriptor, final DebugProcessImpl debugProcess) throws ClassNotLoadedException {
     final Value value = descriptor.getValue();
     if(value == null) {
       return null;
@@ -103,10 +105,11 @@
         if(locations.size() > 0) {
           final Location location = locations.get(0);
           return ApplicationManager.getApplication().runReadAction(new Computable<SourcePosition>() {
+            @Override
             public SourcePosition compute() {
               SourcePosition position = debugProcess.getPositionManager().getSourcePosition(location);
               // adjust position for non-anonymous classes
-              if (clsType.name().indexOf("$") < 0) {
+              if (clsType.name().indexOf('$') < 0) {
                 final PsiClass classAt = position != null? JVMNameUtil.getClassAt(position) : null;
                 if (classAt != null) {
                   final SourcePosition classPosition = SourcePosition.createFromElement(classAt);
@@ -130,13 +133,15 @@
     return null;
   }
 
-  private class NavigateCommand extends SourcePositionCommand {
+  private static class NavigateCommand extends SourcePositionCommand {
     public NavigateCommand(final DebuggerContextImpl debuggerContext, final ValueDescriptor descriptor, final DebugProcessImpl debugProcess, final AnActionEvent e) {
       super(debuggerContext, descriptor, debugProcess, e);
     }
+    @Override
     protected NavigateCommand createRetryCommand() {
       return new NavigateCommand(myDebuggerContext, myDescriptor, myDebugProcess, myActionEvent);
     }
+    @Override
     protected void doAction(final SourcePosition sourcePosition) {
       if (sourcePosition != null) {
         sourcePosition.navigate(true);
@@ -144,19 +149,21 @@
     }
   }
 
-  private class EnableCommand extends SourcePositionCommand {
+  private static class EnableCommand extends SourcePositionCommand {
     public EnableCommand(final DebuggerContextImpl debuggerContext, final ValueDescriptor descriptor, final DebugProcessImpl debugProcess, final AnActionEvent e) {
       super(debuggerContext, descriptor, debugProcess, e);
     }
+    @Override
     protected EnableCommand createRetryCommand() {
       return new EnableCommand(myDebuggerContext, myDescriptor, myDebugProcess, myActionEvent);
     }
+    @Override
     protected void doAction(final SourcePosition sourcePosition) {
       enableAction(myActionEvent, sourcePosition != null);
     }
   }
 
-  public abstract class SourcePositionCommand extends SuspendContextCommandImpl {
+  public abstract static class SourcePositionCommand extends SuspendContextCommandImpl {
     protected final DebuggerContextImpl myDebuggerContext;
     protected final ValueDescriptor myDescriptor;
     protected final DebugProcessImpl myDebugProcess;
@@ -173,6 +180,7 @@
       myActionEvent = actionEvent;
     }
 
+    @Override
     public final void contextAction() throws Exception {
       try {
         doAction(calcPosition(myDescriptor, myDebugProcess));
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/QuickEvaluateActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/QuickEvaluateActionHandler.java
index d67b2bf..6eedff4 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/QuickEvaluateActionHandler.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/QuickEvaluateActionHandler.java
@@ -21,34 +21,37 @@
 package com.intellij.debugger.actions;
 
 import com.intellij.debugger.DebuggerManagerEx;
-import com.intellij.debugger.settings.DebuggerSettings;
 import com.intellij.debugger.impl.DebuggerSession;
+import com.intellij.debugger.settings.DebuggerSettings;
 import com.intellij.debugger.ui.ValueHint;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
-import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler;
 import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint;
+import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler;
 import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType;
 import org.jetbrains.annotations.NotNull;
 
 import java.awt.*;
 
 public class QuickEvaluateActionHandler extends QuickEvaluateHandler {
-
+  @Override
   public boolean isEnabled(@NotNull final Project project) {
     DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(project).getContext().getDebuggerSession();
     return debuggerSession != null && debuggerSession.isPaused();
   }
 
+  @Override
   public AbstractValueHint createValueHint(@NotNull final Project project, @NotNull final Editor editor, @NotNull final Point point, final ValueHintType type) {
     return ValueHint.createValueHint(project, editor, point, type);
   }
 
+  @Override
   public boolean canShowHint(@NotNull final Project project) {
     DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(project).getContext().getDebuggerSession();
     return debuggerSession != null && debuggerSession.isAttached();
   }
 
+  @Override
   public int getValueLookupDelay(final Project project) {
     return DebuggerSettings.getInstance().VALUE_LOOKUP_DELAY;
   }
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ToggleBreakpointEnabledAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ToggleBreakpointEnabledAction.java
index fda3e61..693b7f4 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/ToggleBreakpointEnabledAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/ToggleBreakpointEnabledAction.java
@@ -22,7 +22,6 @@
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.actionSystem.Presentation;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.fileEditor.FileEditorManager;
@@ -41,7 +40,7 @@
     Breakpoint breakpoint = findBreakpoint(project);
     if (breakpoint != null) {
       final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager();
-      breakpointManager.setBreakpointEnabled(breakpoint, !breakpoint.ENABLED);
+      breakpointManager.setBreakpointEnabled(breakpoint, !breakpoint.isEnabled());
     }
   }
 
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ToggleFieldBreakpointAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ToggleFieldBreakpointAction.java
index 39a3977..a7e00ee 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/ToggleFieldBreakpointAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/ToggleFieldBreakpointAction.java
@@ -81,7 +81,7 @@
                   long id = object.uniqueID();
                   InstanceFilter[] instanceFilters = new InstanceFilter[] { InstanceFilter.create(Long.toString(id))};
                   fieldBreakpoint.setInstanceFilters(instanceFilters);
-                  fieldBreakpoint.INSTANCE_FILTERS_ENABLED = true;
+                  fieldBreakpoint.setInstanceFiltersEnabled(true);
                 }
               }
             }
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ToggleLineBreakpointActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/ToggleLineBreakpointActionHandler.java
deleted file mode 100644
index 650e7c3..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/actions/ToggleLineBreakpointActionHandler.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.actions;
-
-import com.intellij.codeInsight.folding.impl.actions.ExpandRegionAction;
-import com.intellij.debugger.DebuggerManagerEx;
-import com.intellij.debugger.engine.DebuggerUtils;
-import com.intellij.debugger.engine.requests.RequestManagerImpl;
-import com.intellij.debugger.ui.breakpoints.Breakpoint;
-import com.intellij.debugger.ui.breakpoints.BreakpointManager;
-import com.intellij.debugger.ui.breakpoints.LineBreakpoint;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.FoldRegion;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.xdebugger.impl.actions.DebuggerActionHandler;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class ToggleLineBreakpointActionHandler extends DebuggerActionHandler {
-
-  private final boolean myTemporary;
-
-  public ToggleLineBreakpointActionHandler(boolean temporary) {
-
-    myTemporary = temporary;
-  }
-
-  public boolean isEnabled(@NotNull final Project project, final AnActionEvent event) {
-    PlaceInDocument place = getPlace(project, event);
-    if (place != null) {
-      final Document document = place.getDocument();
-      final int offset = place.getOffset();
-      int line = document.getLineNumber(offset);
-
-      VirtualFile file = FileDocumentManager.getInstance().getFile(document);
-      PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
-      if (DebuggerUtils.supportsJVMDebugging(file.getFileType()) || DebuggerUtils.supportsJVMDebugging(psiFile)) {
-        final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager();
-        return breakpointManager.findBreakpoint(document, offset, LineBreakpoint.CATEGORY) != null ||
-                   LineBreakpoint.canAddLineBreakpoint(project, document, line);
-      }
-    }
-
-    return false;
-  }
-
-  public void perform(@NotNull final Project project, final AnActionEvent event) {
-    PlaceInDocument place = getPlace(project, event);
-    if(place == null) {
-      return;
-    }
-
-    Editor editor = event.getData(CommonDataKeys.EDITOR);
-    ExpandRegionAction.expandRegionAtCaret(project, editor);
-
-    Document document = place.getDocument();
-    int line = document.getLineNumber(place.getOffset());
-    if (editor != null && editor.getCaretModel().getVisualPosition().line != line) {
-      editor.getCaretModel().moveToOffset(place.getOffset());
-    }
-
-    DebuggerManagerEx debugManager = DebuggerManagerEx.getInstanceEx(project);
-    if (debugManager == null) {
-      return;
-    }
-    BreakpointManager manager = debugManager.getBreakpointManager();
-    final Breakpoint breakpoint = manager.findBreakpoint(document, place.getOffset(), LineBreakpoint.CATEGORY);
-    if(breakpoint == null) {
-      LineBreakpoint lineBreakpoint = manager.addLineBreakpoint(document, line);
-      if(lineBreakpoint != null) {
-        lineBreakpoint.REMOVE_AFTER_HIT = myTemporary;
-        RequestManagerImpl.createRequests(lineBreakpoint);
-      }
-    }
-    else {
-      if (!breakpoint.REMOVE_AFTER_HIT && myTemporary) {
-        breakpoint.REMOVE_AFTER_HIT = true;
-        breakpoint.updateUI();
-      }
-      else {
-        manager.removeBreakpoint(breakpoint);
-      }
-    }
-  }
-
-  private static boolean containsOnlyDeclarations(int line, Document document, PsiFile file) {
-    int lineStart = document.getLineStartOffset(line);
-    int lineEnd = document.getLineEndOffset(line);
-    PsiElement start = file.findElementAt(lineStart);
-    PsiElement end = file.findElementAt(lineEnd - 1);
-    if (start == null || end == null) return false;
-
-    PsiElement commonParent = PsiTreeUtil.findCommonParent(start, end);
-    for (PsiElement element : PsiTreeUtil.findChildrenOfAnyType(commonParent, PsiStatement.class, PsiExpression.class)) {
-      if (new TextRange(lineStart, lineEnd).contains(element.getTextRange().getStartOffset())) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  @Nullable
-  private static PlaceInDocument getPlace(@NotNull final Project project, AnActionEvent event) {
-    Editor editor = event.getData(CommonDataKeys.EDITOR);
-    if(editor == null) {
-      editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
-    }
-    if (editor == null) {
-      return null;
-    }
-    
-    final Document document = editor.getDocument();
-    PsiDocumentManager.getInstance(project).commitDocument(document);
-    PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
-    if (file == null) {
-      return null;
-    }
-
-    // if several lines are merged into one visual line (using folding), try to find the most appropriate of those lines
-    int visualLine = editor.getCaretModel().getVisualPosition().getLine();
-    int visibleOffset = editor.getCaretModel().getOffset();
-    while (editor.offsetToVisualPosition(visibleOffset).line == visualLine) {
-      int line = document.getLineNumber(visibleOffset);
-      if (!containsOnlyDeclarations(line, document, file)) {
-        return new PlaceInDocument(document, visibleOffset);
-      }
-      int lineEndOffset = document.getLineEndOffset(line);
-      FoldRegion region = editor.getFoldingModel().getCollapsedRegionAtOffset(lineEndOffset);
-      if (region != null) {
-        int foldEnd = region.getEndOffset();
-        if (foldEnd > lineEndOffset) {
-          visibleOffset = foldEnd;
-          continue;
-        }
-      }
-      visibleOffset = lineEndOffset + 1;
-    }
-
-    return new PlaceInDocument(document, editor.getCaretModel().getOffset());
-  }
-}
\ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/CompoundPositionManager.java b/java/debugger/impl/src/com/intellij/debugger/engine/CompoundPositionManager.java
index 49d3cae..399c55f 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/CompoundPositionManager.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/CompoundPositionManager.java
@@ -17,22 +17,24 @@
 
 import com.intellij.debugger.NoDataException;
 import com.intellij.debugger.PositionManager;
+import com.intellij.debugger.PositionManagerEx;
 import com.intellij.debugger.SourcePosition;
 import com.intellij.debugger.requests.ClassPrepareRequestor;
-import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.xdebugger.frame.XStackFrame;
 import com.sun.jdi.Location;
 import com.sun.jdi.ReferenceType;
 import com.sun.jdi.request.ClassPrepareRequest;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-public class CompoundPositionManager implements PositionManager{
-  private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.CompoundPositionManager");
+public class CompoundPositionManager extends PositionManagerEx {
   private final ArrayList<PositionManager> myPositionManagers = new ArrayList<PositionManager>();
 
+  @SuppressWarnings("UnusedDeclaration")
   public CompoundPositionManager() {
   }
 
@@ -45,6 +47,7 @@
     myPositionManagers.add(0, manager);
   }
 
+  @Override
   public SourcePosition getSourcePosition(Location location) {
     for (PositionManager positionManager : myPositionManagers) {
       try {
@@ -56,6 +59,7 @@
     return null;
   }
 
+  @Override
   @NotNull
   public List<ReferenceType> getAllClasses(SourcePosition classPosition) {
     for (PositionManager positionManager : myPositionManagers) {
@@ -68,6 +72,7 @@
     return Collections.emptyList();
   }
 
+  @Override
   @NotNull
   public List<Location> locationsOfLine(ReferenceType type, SourcePosition position) {
     for (PositionManager positionManager : myPositionManagers) {
@@ -80,6 +85,7 @@
     return Collections.emptyList();
   }
 
+  @Override
   public ClassPrepareRequest createPrepareRequest(ClassPrepareRequestor requestor, SourcePosition position) {
     for (PositionManager positionManager : myPositionManagers) {
       try {
@@ -91,4 +97,18 @@
 
     return null;
   }
+
+  @Nullable
+  @Override
+  public XStackFrame createStackFrame(@NotNull Location location) {
+    for (PositionManager positionManager : myPositionManagers) {
+      if (positionManager instanceof PositionManagerEx) {
+        XStackFrame xStackFrame = ((PositionManagerEx)positionManager).createStackFrame(location);
+        if (xStackFrame != null) {
+          return xStackFrame;
+        }
+      }
+    }
+    return null;
+  }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/ContextUtil.java b/java/debugger/impl/src/com/intellij/debugger/engine/ContextUtil.java
index bfd7d05..26903c8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/ContextUtil.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/ContextUtil.java
@@ -53,8 +53,8 @@
     try {
       location = frameProxy.location();
     }
-    catch (Throwable th) {
-      LOG.debug(th);
+    catch (Throwable e) {
+      LOG.debug(e);
     }
     final CompoundPositionManager positionManager = debugProcess.getPositionManager();
     if (positionManager == null) {
@@ -63,7 +63,8 @@
     }
     try {
       return positionManager.getSourcePosition(location);
-    } catch (IndexNotReadyException e) {
+    }
+    catch (IndexNotReadyException ignored) {
       return null;
     }
   }
@@ -124,10 +125,10 @@
       }
       return codeBlockFromText;
     }
-    catch (IncorrectOperationException e) {
+    catch (IncorrectOperationException ignored) {
       return element;
     }
-    catch (EvaluateException e) {
+    catch (EvaluateException ignored) {
       return element;
     }
     finally {
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java
index a5b1be2..b660d5f 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java
@@ -57,9 +57,9 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.UserDataHolderBase;
 import com.intellij.openapi.wm.ToolWindowId;
 import com.intellij.openapi.wm.WindowManager;
 import com.intellij.psi.PsiDocumentManager;
@@ -77,6 +77,7 @@
 import com.sun.jdi.request.EventRequest;
 import com.sun.jdi.request.EventRequestManager;
 import com.sun.jdi.request.StepRequest;
+import gnu.trove.THashMap;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -88,7 +89,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
-public abstract class DebugProcessImpl implements DebugProcess {
+public abstract class DebugProcessImpl extends UserDataHolderBase implements DebugProcess {
   private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.DebugProcessImpl");
 
   @NonNls private static final String SOCKET_ATTACHING_CONNECTOR_NAME = "com.sun.jdi.SocketAttach";
@@ -111,26 +112,26 @@
   protected static final int STATE_DETACHED  = 3;
   protected final AtomicInteger myState = new AtomicInteger(STATE_INITIAL);
 
-  private ExecutionResult  myExecutionResult;
+  private ExecutionResult myExecutionResult;
   private RemoteConnection myConnection;
 
   private ConnectionServiceWrapper myConnectionService;
   private Map<String, Connector.Argument> myArguments;
 
   private final List<NodeRenderer> myRenderers = new ArrayList<NodeRenderer>();
-  private final Map<Type, NodeRenderer>  myNodeRederersMap = new com.intellij.util.containers.HashMap<Type, NodeRenderer>();
-  private final NodeRendererSettingsListener  mySettingsListener = new NodeRendererSettingsListener() {
-      public void renderersChanged() {
-        myNodeRederersMap.clear();
-        myRenderers.clear();
-        loadRenderers();
-      }
-    };
+  private final Map<Type, NodeRenderer> myNodeRenderersMap = new THashMap<Type, NodeRenderer>();
+  private final NodeRendererSettingsListener mySettingsListener = new NodeRendererSettingsListener() {
+    @Override
+    public void renderersChanged() {
+      myNodeRenderersMap.clear();
+      myRenderers.clear();
+      loadRenderers();
+    }
+  };
 
   private final SuspendManagerImpl mySuspendManager = new SuspendManagerImpl(this);
   protected CompoundPositionManager myPositionManager = null;
   private volatile DebuggerManagerThreadImpl myDebuggerManagerThread;
-  private final HashMap myUserData = new HashMap();
   private static final int LOCAL_START_TIMEOUT = 30000;
 
   private final Semaphore myWaitFor = new Semaphore();
@@ -141,9 +142,6 @@
   private final Disposable myDisposable = Disposer.newDisposable();
   private final Alarm myStatusUpdateAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, myDisposable);
 
-  /** @noinspection FieldCanBeLocal*/
-  private volatile boolean myDebugProcessStarted = false;
-
   protected DebugProcessImpl(Project project) {
     myProject = project;
     myRequestManager = new RequestManagerImpl(this);
@@ -153,6 +151,7 @@
 
   private void loadRenderers() {
     getManagerThread().invoke(new DebuggerCommandImpl() {
+      @Override
       protected void action() throws Exception {
         try {
           final NodeRendererSettings rendererSettings = NodeRendererSettings.getInstance();
@@ -164,6 +163,7 @@
         }
         finally {
           DebuggerInvocationUtil.swingInvokeLater(myProject, new Runnable() {
+            @Override
             public void run() {
               final DebuggerSession session = mySession;
               if (session != null && session.isAttached()) {
@@ -215,7 +215,7 @@
       return getDefaultRenderer(type);
     }
 
-    NodeRenderer renderer = myNodeRederersMap.get(type);
+    NodeRenderer renderer = myNodeRenderersMap.get(type);
     if(renderer == null) {
       for (final NodeRenderer nodeRenderer : myRenderers) {
         if (nodeRenderer.isApplicable(type)) {
@@ -226,7 +226,7 @@
       if (renderer == null) {
         renderer = getDefaultRenderer(type);
       }
-      myNodeRederersMap.put(type, renderer);
+      myNodeRenderersMap.put(type, renderer);
     }
 
     return renderer;
@@ -308,7 +308,7 @@
   private void stopConnecting() {
     DebuggerManagerThreadImpl.assertIsManagerThread();
 
-    Map arguments = myArguments;
+    Map<String, Connector.Argument> arguments = myArguments;
     try {
       if (arguments == null) {
         return;
@@ -423,7 +423,7 @@
       final List<StepRequest> toDelete = new ArrayList<StepRequest>(stepRequests.size());
       for (final StepRequest request : stepRequests) {
         ThreadReference threadReference = request.thread();
-        // [jeka] on attempt to delete a request assigned to a thread with unknown status, a JDWP error occures
+        // [jeka] on attempt to delete a request assigned to a thread with unknown status, a JDWP error occurs
         try {
           if (threadReference.status() != ThreadReference.THREAD_STATUS_UNKNOWN && (stepThread == null || stepThread.equals(threadReference))) {
             toDelete.add(request);
@@ -444,7 +444,7 @@
         StackFrameProxyImpl stackFrame = thread.frame(0);
         if (stackFrame != null) {
           Location location = stackFrame.location();
-          ReferenceType referenceType = location.declaringType();
+          ReferenceType referenceType = location == null ? null : location.declaringType();
           if (referenceType != null) {
             return referenceType.name();
           }
@@ -477,7 +477,7 @@
         if (address == null) {
           throw new CantRunException(DebuggerBundle.message("error.no.debug.listen.port"));
         }
-        // negative port number means the caller leaves to debugger to decide at which hport to listen
+        // negative port number means the caller leaves to debugger to decide at which port to listen
         //noinspection HardCodedStringLiteral
         final Connector.Argument portArg = myConnection.isUseSockets() ? myArguments.get("port") : myArguments.get("name");
         if (portArg != null) {
@@ -498,10 +498,10 @@
             try {
               connector.stopListening(myArguments);
             }
-            catch (IllegalArgumentException e) {
+            catch (IllegalArgumentException ignored) {
               // ignored
             }
-            catch (IllegalConnectorArgumentsException e) {
+            catch (IllegalConnectorArgumentsException ignored) {
               // ignored
             }
           }
@@ -572,6 +572,7 @@
     if (!myStatusUpdateAlarm.isDisposed()) {
       myStatusUpdateAlarm.cancelAllRequests();
       myStatusUpdateAlarm.addRequest(new Runnable() {
+        @Override
         public void run() {
           final WindowManager wm = WindowManager.getInstance();
           if (wm != null) {
@@ -614,6 +615,7 @@
     final String version = vm.version();
     if ("1.4.0".equals(version)) {
       SwingUtilities.invokeLater(new Runnable() {
+        @Override
         public void run() {
           Messages.showMessageDialog(
             getProject(),
@@ -633,10 +635,12 @@
     myEvaluationDispatcher.removeListener(evaluationListener);
   }
 
+  @Override
   public void addDebugProcessListener(DebugProcessListener listener) {
     myDebugProcessDispatcher.addListener(listener);
   }
 
+  @Override
   public void removeDebugProcessListener(DebugProcessListener listener) {
     myDebugProcessDispatcher.removeListener(listener);
   }
@@ -668,18 +672,12 @@
     return myConnection;
   }
 
+  @Override
   public ExecutionResult getExecutionResult() {
     return myExecutionResult;
   }
 
-  public <T> T getUserData(Key<T> key) {
-    return (T)myUserData.get(key);
-  }
-
-  public <T> void putUserData(Key<T> key, T value) {
-    myUserData.put(key, value);
-  }
-
+  @Override
   public Project getProject() {
     return myProject;
   }
@@ -698,22 +696,27 @@
     return myState.get() == STATE_INITIAL;
   }
 
+  @Override
   public boolean isAttached() {
     return myState.get() == STATE_ATTACHED;
   }
 
+  @Override
   public boolean isDetached() {
     return myState.get() == STATE_DETACHED;
   }
 
+  @Override
   public boolean isDetaching() {
     return myState.get() == STATE_DETACHING;
   }
 
+  @Override
   public RequestManagerImpl getRequestsManager() {
     return myRequestManager;
   }
 
+  @Override
   public VirtualMachineProxyImpl getVirtualMachineProxy() {
     DebuggerManagerThreadImpl.assertIsManagerThread();
     final VirtualMachineProxyImpl vm = myVirtualMachineProxy;
@@ -723,6 +726,7 @@
     return vm;
   }
 
+  @Override
   public void appendPositionManager(final PositionManager positionManager) {
     DebuggerManagerThreadImpl.assertIsManagerThread();
     myPositionManager.appendPositionManager(positionManager);
@@ -756,7 +760,7 @@
         myVirtualMachineProxy = null;
         myPositionManager = null;
         myReturnValueWatcher = null;
-        myNodeRederersMap.clear();
+        myNodeRenderersMap.clear();
         myRenderers.clear();
         DebuggerUtils.cleanupAfterProcessFinish(this);
         myState.set(STATE_DETACHED);
@@ -852,6 +856,7 @@
     Disposer.dispose(myDisposable);
   }
 
+  @Override
   public DebuggerManagerThreadImpl getManagerThread() {
     if (myDebuggerManagerThread == null) {
       synchronized (this) {
@@ -868,11 +873,13 @@
     return suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD ? ObjectReference.INVOKE_SINGLE_THREADED : 0;
   }
 
+  @Override
   public void waitFor() {
     LOG.assertTrue(!DebuggerManagerThreadImpl.isManagerThread());
     myWaitFor.waitFor();
   }
 
+  @Override
   public void waitFor(long timeout) {
     LOG.assertTrue(!DebuggerManagerThreadImpl.isManagerThread());
     myWaitFor.waitFor(timeout);
@@ -1002,6 +1009,7 @@
       final Exception[] exception = new Exception[1];
       final Value[] result = new Value[1];
       getManagerThread().startLongProcessAndFork(new Runnable() {
+        @Override
         public void run() {
           ThreadReferenceProxyImpl thread = context.getThread();
           try {
@@ -1075,14 +1083,17 @@
     }
   }
 
+  @Override
   public Value invokeMethod(final EvaluationContext evaluationContext, final ObjectReference objRef, final Method method, final List args) throws EvaluateException {
     return invokeInstanceMethod(evaluationContext, objRef, method, args, 0);
   }
 
+  @Override
   public Value invokeInstanceMethod(final EvaluationContext evaluationContext, final ObjectReference objRef, final Method method,
                                      final List args, final int invocationOptions) throws EvaluateException {
     final ThreadReference thread = getEvaluationThread(evaluationContext);
     return new InvokeCommand<Value>(args) {
+      @Override
       protected Value invokeMethod(int invokePolicy, final List args) throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
         if (LOG.isDebugEnabled()) {
           LOG.debug("Invoke " + method.name());
@@ -1100,12 +1111,14 @@
     return evaluationThread.getThreadReference();
   }
 
+  @Override
   public Value invokeMethod(final EvaluationContext evaluationContext, final ClassType classType,
                             final Method method,
                             final List args) throws EvaluateException {
 
     final ThreadReference thread = getEvaluationThread(evaluationContext);
     InvokeCommand<Value> invokeCommand = new InvokeCommand<Value>(args) {
+      @Override
       protected Value invokeMethod(int invokePolicy, final List args) throws InvocationException,
                                                                              ClassNotLoadedException,
                                                                              IncompatibleThreadStateException,
@@ -1119,17 +1132,20 @@
     return invokeCommand.start((EvaluationContextImpl)evaluationContext, method);
   }
 
+  @Override
   public ArrayReference newInstance(final ArrayType arrayType,
                                     final int dimension)
     throws EvaluateException {
     return arrayType.newInstance(dimension);
   }
 
+  @Override
   public ObjectReference newInstance(final EvaluationContext evaluationContext, final ClassType classType,
                                      final Method method,
                                      final List args) throws EvaluateException {
     final ThreadReference thread = getEvaluationThread(evaluationContext);
     InvokeCommand<ObjectReference> invokeCommand = new InvokeCommand<ObjectReference>(args) {
+      @Override
       protected ObjectReference invokeMethod(int invokePolicy, final List args) throws InvocationException,
                                                                                        ClassNotLoadedException,
                                                                                        IncompatibleThreadStateException,
@@ -1181,6 +1197,7 @@
     showStatusText("");
   }
 
+  @Override
   public ReferenceType findClass(EvaluationContext evaluationContext, String className,
                                  ClassLoaderReference classLoader) throws EvaluateException {
     try {
@@ -1255,7 +1272,7 @@
     }
   }
 
-  @SuppressWarnings({"HardCodedStringLiteral"})
+  @SuppressWarnings({"HardCodedStringLiteral", "SpellCheckingInspection"})
   public ReferenceType loadClass(EvaluationContextImpl evaluationContext, String qName, ClassLoaderReference classLoader)
     throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException, EvaluateException {
 
@@ -1308,13 +1325,15 @@
     return mySuspendManager;
   }
 
+  @Override
   public CompoundPositionManager getPositionManager() {
     return myPositionManager;
   }
   //ManagerCommands
 
+  @Override
   public void stop(boolean forceTerminate) {
-    this.getManagerThread().terminateAndInvoke(createStopCommand(forceTerminate), DebuggerManagerThreadImpl.COMMAND_TIMEOUT);
+    getManagerThread().terminateAndInvoke(createStopCommand(forceTerminate), DebuggerManagerThreadImpl.COMMAND_TIMEOUT);
   }
 
   public StopCommand createStopCommand(boolean forceTerminate) {
@@ -1328,10 +1347,12 @@
       myIsTerminateTargetVM = isTerminateTargetVM;
     }
 
+    @Override
     public Priority getPriority() {
       return Priority.HIGH;
     }
 
+    @Override
     protected void action() throws Exception {
       if (isAttached()) {
         final VirtualMachineProxyImpl virtualMachineProxy = getVirtualMachineProxy();
@@ -1339,8 +1360,7 @@
           virtualMachineProxy.exit(-1);
         }
         else {
-          // some VM's (like IBM VM 1.4.2 bundled with WebSpere) does not
-          // resume threads on dispose() like it should
+          // some VMs (like IBM VM 1.4.2 bundled with WebSphere) does not resume threads on dispose() like it should
           try {
             virtualMachineProxy.resume();
           }
@@ -1360,6 +1380,7 @@
       super(suspendContext);
     }
 
+    @Override
     public void contextAction() {
       showStatusText(DebuggerBundle.message("status.step.out"));
       final SuspendContextImpl suspendContext = getSuspendContext();
@@ -1391,6 +1412,7 @@
         null;
     }
 
+    @Override
     public void contextAction() {
       showStatusText(DebuggerBundle.message("status.step.into"));
       final SuspendContextImpl suspendContext = getSuspendContext();
@@ -1409,7 +1431,7 @@
       hint.setIgnoreFilters(myForcedIgnoreFilters || mySession.shouldIgnoreSteppingFilters());
       applyThreadFilter(stepThread);
       if (myBreakpoint != null) {
-        myBreakpoint.SUSPEND_POLICY = suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD? DebuggerSettings.SUSPEND_THREAD : DebuggerSettings.SUSPEND_ALL;
+        myBreakpoint.setSuspendPolicy(suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD? DebuggerSettings.SUSPEND_THREAD : DebuggerSettings.SUSPEND_ALL);
         myBreakpoint.createRequest(suspendContext.getDebugProcess());
         myRunToCursorBreakpoint = myBreakpoint;
       }
@@ -1426,11 +1448,12 @@
       myIsIgnoreBreakpoints = ignoreBreakpoints;
     }
 
+    @Override
     public void contextAction() {
       showStatusText(DebuggerBundle.message("status.step.over"));
       final SuspendContextImpl suspendContext = getSuspendContext();
       final ThreadReferenceProxyImpl stepThread = getContextThread();
-      // need this hint whil stepping over for JSR45 support:
+      // need this hint while stepping over for JSR45 support:
       // several lines of generated java code may correspond to a single line in the source file,
       // from which the java code was generated
       RequestHint hint = new RequestHint(stepThread, suspendContext, StepRequest.STEP_OVER);
@@ -1464,6 +1487,7 @@
       myRunToCursorBreakpoint = breakpointManager.addRunToCursorBreakpoint(document, lineIndex, ignoreBreakpoints);
     }
 
+    @Override
     public void contextAction() {
       showStatusText(DebuggerBundle.message("status.run.to.cursor"));
       cancelRunToCursorBreakpoint();
@@ -1476,8 +1500,7 @@
       }
       applyThreadFilter(getContextThread());
       final SuspendContextImpl context = getSuspendContext();
-      myRunToCursorBreakpoint.SUSPEND_POLICY = context.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD? DebuggerSettings.SUSPEND_THREAD : DebuggerSettings.SUSPEND_ALL;
-      myRunToCursorBreakpoint.LOG_ENABLED = false;
+      myRunToCursorBreakpoint.setSuspendPolicy(context.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD? DebuggerSettings.SUSPEND_THREAD : DebuggerSettings.SUSPEND_ALL);
       myRunToCursorBreakpoint.createRequest(context.getDebugProcess());
       DebugProcessImpl.this.myRunToCursorBreakpoint = myRunToCursorBreakpoint;
       super.contextAction();
@@ -1494,10 +1517,12 @@
       myContextThread = contextThread != null ? contextThread : (suspendContext != null? suspendContext.getThread() : null);
     }
 
+    @Override
     public Priority getPriority() {
       return Priority.HIGH;
     }
 
+    @Override
     public void contextAction() {
       showStatusText(DebuggerBundle.message("status.process.resumed"));
       getSuspendManager().resume(getSuspendContext());
@@ -1524,6 +1549,7 @@
     public PauseCommand() {
     }
 
+    @Override
     public void action() {
       if (!isAttached() || getVirtualMachineProxy().isPausePressed()) {
         return;
@@ -1544,6 +1570,7 @@
       myThread = thread;
     }
 
+    @Override
     public void contextAction() {
       if (getSuspendManager().isFrozen(myThread)) {
         getSuspendManager().unfreezeThread(myThread);
@@ -1553,7 +1580,7 @@
       final Set<SuspendContextImpl> suspendingContexts = SuspendManagerUtil.getSuspendingContexts(getSuspendManager(), myThread);
       for (SuspendContextImpl suspendContext : suspendingContexts) {
         if (suspendContext.getThread() == myThread) {
-          DebugProcessImpl.this.getManagerThread().invoke(createResumeCommand(suspendContext));
+          getManagerThread().invoke(createResumeCommand(suspendContext));
         }
         else {
           getSuspendManager().resumeThread(suspendContext, myThread);
@@ -1569,6 +1596,7 @@
       myThread = thread;
     }
 
+    @Override
     protected void action() throws Exception {
       SuspendManager suspendManager = getSuspendManager();
       if (!suspendManager.isFrozen(myThread)) {
@@ -1585,6 +1613,7 @@
       myStackFrame = frameProxy;
     }
 
+    @Override
     public void contextAction() {
       final ThreadReferenceProxyImpl thread = myStackFrame.threadProxy();
       try {
@@ -1593,7 +1622,7 @@
           return;
         }
       }
-      catch (ObjectCollectedException e) {
+      catch (ObjectCollectedException ignored) {
         notifyCancelled();
         return;
       }
@@ -1606,6 +1635,7 @@
 
       if (myStackFrame.isBottom()) {
         DebuggerInvocationUtil.swingInvokeLater(myProject, new Runnable() {
+          @Override
           public void run() {
             Messages.showMessageDialog(myProject, DebuggerBundle.message("error.pop.bottom.stackframe"), ActionsBundle.actionText(DebuggerActions.POP_FRAME), Messages.getErrorIcon());
           }
@@ -1618,6 +1648,7 @@
       }
       catch (final EvaluateException e) {
         DebuggerInvocationUtil.swingInvokeLater(myProject, new Runnable() {
+          @Override
           public void run() {
             Messages.showMessageDialog(myProject, DebuggerBundle.message("error.pop.stackframe", e.getLocalizedMessage()), ActionsBundle.actionText(DebuggerActions.POP_FRAME), Messages.getErrorIcon());
           }
@@ -1630,6 +1661,7 @@
     }
   }
 
+  @Override
   @NotNull
   public GlobalSearchScope getSearchScope() {
     LOG.assertTrue(mySession != null, "Accessing debug session before its initialization");
@@ -1668,7 +1700,6 @@
     }
 
     // writing to volatile field ensures the other threads will see the right values in non-volatile fields
-    myDebugProcessStarted = true;
 
     if (ApplicationManager.getApplication().isUnitTestMode()) {
       return myExecutionResult;
@@ -1719,6 +1750,7 @@
 
     final Ref<Boolean> connectorIsReady = Ref.create(false);
     myDebugProcessDispatcher.addListener(new DebugProcessAdapter() {
+      @Override
       public void connectorIsReady() {
         connectorIsReady.set(true);
         semaphore.up();
@@ -1727,7 +1759,8 @@
     });
 
 
-    this.getManagerThread().schedule(new DebuggerCommandImpl() {
+    getManagerThread().schedule(new DebuggerCommandImpl() {
+      @Override
       protected void action() {
         VirtualMachine vm = null;
 
@@ -1744,7 +1777,7 @@
                   try {
                     wait(500);
                   }
-                  catch (InterruptedException ie) {
+                  catch (InterruptedException ignored) {
                     break;
                   }
                 }
@@ -1752,10 +1785,11 @@
               else {
                 fail();
                 if (myExecutionResult != null || !connectorIsReady.get()) {
-                  // propagate exception only in case we succeded to obtain execution result,
+                  // propagate exception only in case we succeeded to obtain execution result,
                   // otherwise if the error is induced by the fact that there is nothing to debug, and there is no need to show
                   // this problem to the user
                   SwingUtilities.invokeLater(new Runnable() {
+                    @Override
                     public void run() {
                       ExecutionUtil.handleExecutionError(myProject, ToolWindowId.DEBUG, sessionName, e);
                     }
@@ -1773,8 +1807,10 @@
         if (vm != null) {
           final VirtualMachine vm1 = vm;
           afterProcessStarted(new Runnable() {
+            @Override
             public void run() {
               getManagerThread().schedule(new DebuggerCommandImpl() {
+                @Override
                 protected void action() throws Exception {
                   commitVM(vm1);
                 }
@@ -1784,6 +1820,7 @@
         }
       }
 
+      @Override
       protected void commandCancelled() {
         try {
           super.commandCancelled();
@@ -1809,6 +1846,7 @@
         removeProcessListener(this);
       }
 
+      @Override
       public void startNotified(ProcessEvent event) {
         run();
       }
@@ -1838,11 +1876,13 @@
   public ResumeCommand createResumeCommand(SuspendContextImpl suspendContext, final PrioritizedTask.Priority priority) {
     final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(getProject()).getBreakpointManager();
     return new ResumeCommand(suspendContext) {
+      @Override
       public void contextAction() {
         breakpointManager.applyThreadFilter(DebugProcessImpl.this, null); // clear the filter on resume
         super.contextAction();
       }
 
+      @Override
       public Priority getPriority() {
         return priority;
       }
@@ -1889,6 +1929,7 @@
   public void setBreakpointsMuted(final boolean muted) {
     if (isAttached()) {
       getManagerThread().schedule(new DebuggerCommandImpl() {
+        @Override
         protected void action() throws Exception {
           // set the flag before enabling/disabling cause it affects if breakpoints will create requests
           if (myBreakpointsMuted.getAndSet(muted) != muted) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/requests/LocatableEventRequestor.java b/java/debugger/impl/src/com/intellij/debugger/engine/requests/LocatableEventRequestor.java
index db64d1d..ed1d7af 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/requests/LocatableEventRequestor.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/requests/LocatableEventRequestor.java
@@ -19,16 +19,9 @@
 import com.intellij.debugger.requests.Requestor;
 import com.sun.jdi.event.LocatableEvent;
 
-/**
- * Created by IntelliJ IDEA.
- * User: lex
- * Date: Jun 27, 2003
- * Time: 8:05:52 PM
- * To change this template use Options | File Templates.
- */
 public interface LocatableEventRequestor extends Requestor {
   /**
-   * @returns true if requesto was hit by the event, false otherwise
+   * @returns true if request was hit by the event, false otherwise
    */ 
   boolean processLocatableEvent(SuspendContextCommandImpl action, LocatableEvent event) throws EventProcessingException;
 
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/requests/RequestManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/requests/RequestManagerImpl.java
index 8329587..c35c971 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/requests/RequestManagerImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/requests/RequestManagerImpl.java
@@ -30,9 +30,7 @@
 import com.intellij.debugger.ui.breakpoints.Breakpoint;
 import com.intellij.debugger.ui.breakpoints.BreakpointManager;
 import com.intellij.debugger.ui.breakpoints.FilteredRequestor;
-import com.intellij.openapi.application.AccessToken;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ReadAction;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Computable;
@@ -40,15 +38,10 @@
 import com.intellij.psi.PsiClass;
 import com.intellij.ui.classFilter.ClassFilter;
 import com.intellij.util.containers.HashMap;
-import com.intellij.xdebugger.XDebuggerManager;
-import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
-import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
 import com.sun.jdi.*;
 import com.sun.jdi.event.ClassPrepareEvent;
 import com.sun.jdi.request.*;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.java.debugger.breakpoints.JavaBreakpointAdapter;
-import org.jetbrains.java.debugger.breakpoints.JavaBreakpointType;
 
 import java.util.Collections;
 import java.util.HashSet;
@@ -158,11 +151,11 @@
       request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
     }
 
-    if (requestor.COUNT_FILTER_ENABLED && requestor.COUNT_FILTER > 0) {
-      request.addCountFilter(requestor.COUNT_FILTER);
+    if (requestor.isCountFilterEnabled() && requestor.getCountFilter() > 0) {
+      request.addCountFilter(requestor.getCountFilter());
     }
 
-    if (requestor.CLASS_FILTERS_ENABLED && !(request instanceof BreakpointRequest) /*no built-in class filters support for breakpoint requests*/ ) {
+    if (requestor.isClassFiltersEnabled() && !(request instanceof BreakpointRequest) /*no built-in class filters support for breakpoint requests*/ ) {
       ClassFilter[] classFilters = requestor.getClassFilters();
       if (DebuggerUtilsEx.getEnabledNumber(classFilters) == 1) {
         for (final ClassFilter filter : classFilters) {
@@ -408,17 +401,18 @@
           breakpoint.createRequest(myDebugProcess);
         }
 
-        AccessToken token = ReadAction.start();
-        try {
-          JavaBreakpointAdapter adapter = new JavaBreakpointAdapter(project);
-          for (XLineBreakpoint<XBreakpointProperties> breakpoint : XDebuggerManager.getInstance(project).getBreakpointManager()
-            .getBreakpoints(JavaBreakpointType.class)) {
-            adapter.getOrCreate(breakpoint).createRequest(myDebugProcess);
-          }
-        }
-        finally {
-          token.finish();
-        }
+        //AccessToken token = ReadAction.start();
+        //try {
+        //  JavaBreakpointAdapter adapter = new JavaBreakpointAdapter(project);
+        //  for (XLineBreakpoint breakpoint : XDebuggerManager.getInstance(project).getBreakpointManager()
+        //    .getBreakpoints(JavaLineBreakpointType.class)) {
+        //    //new JavaLineBreakpointRequestor(breakpoint).createRequest(myDebugProcess);
+        //    //adapter.getOrCreate(breakpoint).createRequest(myDebugProcess);
+        //  }
+        //}
+        //finally {
+        //  token.finish();
+        //}
       }
     });
   }
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextImpl.java
index e35ba83..640f76c 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextImpl.java
@@ -42,7 +42,7 @@
 public final class DebuggerContextImpl implements DebuggerContext {
   private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.DebuggerContextImpl");
 
-  public static final DebuggerContextImpl EMPTY_CONTEXT = DebuggerContextImpl.createDebuggerContext((DebuggerSession) null, null, null, null);
+  public static final DebuggerContextImpl EMPTY_CONTEXT = createDebuggerContext((DebuggerSession)null, null, null, null);
 
   private boolean myInitialized;
 
@@ -58,7 +58,7 @@
 
   private DebuggerContextImpl(@Nullable DebuggerSession session, DebugProcessImpl debugProcess, SuspendContextImpl context, ThreadReferenceProxyImpl threadProxy, StackFrameProxyImpl frameProxy, SourcePosition position, PsiElement contextElement, boolean initialized) {
     LOG.assertTrue(frameProxy == null || threadProxy == null || threadProxy == frameProxy.threadProxy());
-    LOG.assertTrue(debugProcess == null ? frameProxy == null && threadProxy == null : true);
+    LOG.assertTrue(debugProcess != null || frameProxy == null && threadProxy == null);
     myDebuggerSession = session;
     myThreadProxy = threadProxy;
     myFrameProxy = frameProxy;
@@ -74,6 +74,7 @@
     return myDebuggerSession;
   }
 
+  @Override
   public DebugProcessImpl getDebugProcess() {
     return myDebugProcess;
   }
@@ -82,14 +83,17 @@
     return myThreadProxy;
   }
 
+  @Override
   public SuspendContextImpl getSuspendContext() {
     return mySuspendContext;
   }
 
+  @Override
   public Project getProject() {
     return myDebugProcess != null ? myDebugProcess.getProject() : null;
   }
 
+  @Override
   @Nullable
   public StackFrameProxyImpl getFrameProxy() {
     LOG.assertTrue(myInitialized);
@@ -144,13 +148,14 @@
         try {
           myFrameProxy = myThreadProxy.frameCount() > 0 ? myThreadProxy.frame(0) : null;
         }
-        catch (EvaluateException e) {
+        catch (EvaluateException ignored) {
         }
       }
     }
 
     if(myFrameProxy != null) {
       PsiDocumentManager.getInstance(getProject()).commitAndRunReadAction(new Runnable() {
+        @Override
         public void run() {
           if (mySourcePosition == null) {
             mySourcePosition = ContextUtil.getSourcePosition(DebuggerContextImpl.this);
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java
index 917dba2..7837eab 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java
@@ -16,7 +16,6 @@
 package com.intellij.debugger.impl;
 
 import com.intellij.debugger.*;
-import com.intellij.debugger.actions.DebuggerActions;
 import com.intellij.debugger.engine.*;
 import com.intellij.debugger.engine.evaluation.EvaluateException;
 import com.intellij.debugger.engine.evaluation.EvaluationListener;
@@ -56,6 +55,7 @@
 import com.intellij.unscramble.ThreadState;
 import com.intellij.util.Alarm;
 import com.intellij.xdebugger.AbstractDebuggerSession;
+import com.intellij.xdebugger.impl.actions.XDebuggerActions;
 import com.intellij.xdebugger.impl.evaluate.quick.common.ValueLookupManager;
 import com.sun.jdi.ObjectCollectedException;
 import com.sun.jdi.ThreadReference;
@@ -115,6 +115,7 @@
 
   @NotNull
   public GlobalSearchScope getSearchScope() {
+    //noinspection ConstantConditions
     LOG.assertTrue(mySearchScope != null, "Accessing Session's search scope before its initialization");
     return mySearchScope;
   }
@@ -134,6 +135,7 @@
       myDebuggerContext = SESSION_EMPTY_CONTEXT;
     }
 
+    @Override
     public DebuggerContextImpl getContext() {
       return myDebuggerContext;
     }
@@ -146,11 +148,13 @@
      * in this case we assume that the latter setState is ignored
      * since the thread was resumed
      */
+    @Override
     public void setState(final DebuggerContextImpl context, final int state, final int event, final String description) {
       ApplicationManager.getApplication().assertIsDispatchThread();
       final DebuggerSession session = context.getDebuggerSession();
       LOG.assertTrue(session == DebuggerSession.this || session == null);
       final Runnable setStateRunnable = new Runnable() {
+        @Override
         public void run() {
           LOG.assertTrue(myDebuggerContext.isInitialised());
           myDebuggerContext = context;
@@ -170,6 +174,7 @@
       }
       else {
         getProcess().getManagerThread().schedule(new SuspendContextCommandImpl(context.getSuspendContext()) {
+          @Override
           public void contextAction() throws Exception {
             context.initCaches();
             DebuggerInvocationUtil.swingInvokeLater(getProject(), setStateRunnable);
@@ -279,7 +284,7 @@
       resumeAction(runToCursorCommand, EVENT_STEP);
     }
     catch (EvaluateException e) {
-      Messages.showErrorDialog(e.getMessage(), ActionsBundle.actionText(DebuggerActions.RUN_TO_CURSOR));
+      Messages.showErrorDialog(e.getMessage(), ActionsBundle.actionText(XDebuggerActions.RUN_TO_CURSOR));
     }
   }
 
@@ -335,6 +340,7 @@
   }
 
   // ManagerCommands
+  @Override
   public boolean isStopped() {
     return getState() == STATE_STOPPED;
   }
@@ -343,6 +349,7 @@
     return !isStopped() && getState() != STATE_WAITING_ATTACH;
   }
 
+  @Override
   public boolean isPaused() {
     return getState() == STATE_PAUSED;
   }
@@ -399,18 +406,21 @@
     }
 
     //executed in manager thread
+    @Override
     public void connectorIsReady() {
       DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
+        @Override
         public void run() {
           RemoteConnection connection = myDebugProcess.getConnection();
           final String addressDisplayName = DebuggerBundle.getAddressDisplayName(connection);
           final String transportName = DebuggerBundle.getTransportName(connection);
           final String connectionStatusMessage = connection.isServerMode() ? DebuggerBundle.message("status.listening", addressDisplayName, transportName) : DebuggerBundle.message("status.connecting", addressDisplayName, transportName);
-          getContextManager().setState(SESSION_EMPTY_CONTEXT, DebuggerSession.STATE_WAITING_ATTACH, DebuggerSession.EVENT_START_WAIT_ATTACH, connectionStatusMessage);
+          getContextManager().setState(SESSION_EMPTY_CONTEXT, STATE_WAITING_ATTACH, EVENT_START_WAIT_ATTACH, connectionStatusMessage);
         }
       });
     }
 
+    @Override
     public void paused(final SuspendContextImpl suspendContext) {
       if (LOG.isDebugEnabled()) {
         LOG.debug("paused");
@@ -418,6 +428,7 @@
 
       if (!shouldSetAsActiveContext(suspendContext)) {
         DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
+          @Override
           public void run() {
             getContextManager().fireStateChanged(getContextManager().getContext(), EVENT_THREADS_REFRESH);
           }
@@ -470,7 +481,7 @@
             }
             proxy = (currentThread.frameCount() > 0) ? currentThread.frame(0) : null;
           }
-          catch (ObjectCollectedException e) {
+          catch (ObjectCollectedException ignored) {
             proxy = null;
           }
           catch (EvaluateException e) {
@@ -498,6 +509,7 @@
       }
 
       SourcePosition position = PsiDocumentManager.getInstance(getProject()).commitAndRunReadAction(new Computable<SourcePosition>() {
+        @Override
         public @Nullable SourcePosition compute() {
           return ContextUtil.getSourcePosition(positionContext);
         }
@@ -507,7 +519,7 @@
         final List<Pair<Breakpoint, Event>> eventDescriptors = DebuggerUtilsEx.getEventDescriptors(suspendContext);
         final RequestManagerImpl requestsManager = suspendContext.getDebugProcess().getRequestsManager();
         final PsiFile foundFile = position.getFile();
-        final boolean sourceMissing = foundFile == null || foundFile instanceof PsiCompiledElement;
+        final boolean sourceMissing = foundFile instanceof PsiCompiledElement;
         for (Pair<Breakpoint, Event> eventDescriptor : eventDescriptors) {
           Breakpoint breakpoint = eventDescriptor.getFirst();
           if (breakpoint instanceof LineBreakpoint) {
@@ -525,7 +537,7 @@
               try {
                 className = frameProxy != null? frameProxy.location().declaringType().name() : "";
               }
-              catch (EvaluateException e) {
+              catch (EvaluateException ignored) {
                 className = "";
               }
               requestsManager.setInvalid(breakpoint, DebuggerBundle.message("error.invalid.breakpoint.source.not.found", className));
@@ -539,6 +551,7 @@
       debuggerContext.setPositionCache(position);
 
       DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
+        @Override
         public void run() {
           getContextManager().setState(debuggerContext, STATE_PAUSED, EVENT_PAUSE, null);
         }
@@ -562,9 +575,11 @@
     }
 
 
+    @Override
     public void resumed(final SuspendContextImpl suspendContext) {
       final SuspendContextImpl currentContext = getProcess().getSuspendManager().getPausedContext();
       DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
+        @Override
         public void run() {
           if (currentContext != null) {
             getContextManager().setState(DebuggerContextUtil.createDebuggerContext(DebuggerSession.this, currentContext), STATE_PAUSED, EVENT_CONTEXT, null);
@@ -576,6 +591,7 @@
       });
     }
 
+    @Override
     public void processAttached(final DebugProcessImpl process) {
       final RemoteConnection connection = getProcess().getConnection();
       final String addressDisplayName = DebuggerBundle.getAddressDisplayName(connection);
@@ -584,14 +600,17 @@
 
       process.getExecutionResult().getProcessHandler().notifyTextAvailable(message + "\n", ProcessOutputTypes.SYSTEM);
       DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
+        @Override
         public void run() {
           getContextManager().setState(SESSION_EMPTY_CONTEXT, STATE_RUNNING, EVENT_ATTACHED, message);
         }
       });
     }
 
+    @Override
     public void attachException(final RunProfileState state, final ExecutionException exception, final RemoteConnection remoteConnection) {
       DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
+        @Override
         public void run() {
           String message = "";
           if (state instanceof RemoteState) {
@@ -603,6 +622,7 @@
       });
     }
 
+    @Override
     public void processDetached(final DebugProcessImpl debugProcess, boolean closedByUser) {
       if (!closedByUser) {
         ExecutionResult executionResult = debugProcess.getExecutionResult();
@@ -614,6 +634,7 @@
         }
       }
       DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
+        @Override
         public void run() {
           final RemoteConnection connection = getProcess().getConnection();
           final String addressDisplayName = DebuggerBundle.getAddressDisplayName(connection);
@@ -624,10 +645,12 @@
       mySteppingThroughThreads.clear();
     }
 
+    @Override
     public void threadStarted(DebugProcess proc, ThreadReference thread) {
       notifyThreadsRefresh();
     }
 
+    @Override
     public void threadStopped(DebugProcess proc, ThreadReference thread) {
       notifyThreadsRefresh();
     }
@@ -636,6 +659,7 @@
       if (!myUpdateAlarm.isDisposed()) {
         myUpdateAlarm.cancelAllRequests();
         myUpdateAlarm.addRequest(new Runnable() {
+          @Override
           public void run() {
             final DebuggerStateManager contextManager = getContextManager();
             contextManager.fireStateChanged(contextManager.getContext(), EVENT_THREADS_REFRESH);
@@ -646,13 +670,16 @@
   }
 
   private class MyEvaluationListener implements EvaluationListener {
+    @Override
     public void evaluationStarted(SuspendContextImpl context) {
       myIsEvaluating = true;
     }
 
+    @Override
     public void evaluationFinished(final SuspendContextImpl context) {
       myIsEvaluating = false;
       DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
+        @Override
         public void run() {
           if (context != getSuspendContext()) {
             getContextManager().setState(DebuggerContextUtil.createDebuggerContext(DebuggerSession.this, context), STATE_PAUSED, EVENT_REFRESH, null);
diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java b/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java
index 4ff1adc..5fed479 100644
--- a/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java
@@ -70,7 +70,7 @@
         clearCaches();
       }
       catch (InternalException e) {
-        if (e.errorCode() == 23 /*INVALID_METHODID accoeding to JDI sources*/) {
+        if (e.errorCode() == 23 /*INVALID_METHODID according to JDI sources*/) {
           myIsObsolete = Boolean.TRUE;
           return true;
         }
@@ -83,6 +83,7 @@
     return false;
   }
 
+  @Override
   protected void clearCaches() {
     DebuggerManagerThreadImpl.assertIsManagerThread();
     if (LOG.isDebugEnabled()) {
@@ -100,6 +101,7 @@
    * Use with caution. Better access stackframe data through the Proxy's methods
    */
 
+  @Override
   public StackFrame getStackFrame() throws EvaluateException  {
     DebuggerManagerThreadImpl.assertIsManagerThread();
 
@@ -113,7 +115,7 @@
       catch (IndexOutOfBoundsException e) {
         throw new EvaluateException(e.getMessage(), e);
       }
-      catch (ObjectCollectedException e) {
+      catch (ObjectCollectedException ignored) {
         throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.thread.collected"));
       }
       catch (IncompatibleThreadStateException e) {
@@ -124,6 +126,7 @@
     return myStackFrame;
   }
 
+  @Override
   public int getFrameIndex() throws EvaluateException {
     DebuggerManagerThreadImpl.assertIsManagerThread();
     checkValid();
@@ -151,10 +154,13 @@
 //    return false;
 //  }
 
+  @Override
   public VirtualMachineProxyImpl getVirtualMachine() {
     return (VirtualMachineProxyImpl) myTimer;
   }
 
+  @Nullable
+  @Override
   public Location location() throws EvaluateException {
     InvalidStackFrameException error = null;
     for (int attempt = 0; attempt < 2; attempt++) {
@@ -172,6 +178,7 @@
     return null;
   }
 
+  @Override
   public ThreadReferenceProxyImpl threadProxy() {
     return myThreadProxy;
   }
@@ -197,13 +204,13 @@
           }
           break;
         }
-        catch (InvalidStackFrameException e) {
+        catch (InvalidStackFrameException ignored) {
           clearCaches();
         }
       }
     }
     catch (InternalException e) {
-      // supress some internal errors caused by bugs in specific JDI implementations
+      // suppress some internal errors caused by bugs in specific JDI implementations
       if(e.errorCode() != 23) {
         throw EvaluateExceptionUtil.createEvaluateException(e);
       }
@@ -238,6 +245,7 @@
     return Collections.emptyList();
   }
 
+  @Override
   public LocalVariableProxyImpl visibleVariableByName(String name) throws EvaluateException  {
     DebuggerManagerThreadImpl.assertIsManagerThread();
     final LocalVariable variable = visibleVariableByNameInt(name);
@@ -332,7 +340,7 @@
           myAllValues.put(variable, value);
         }
       }
-      catch (InconsistentDebugInfoException e) {
+      catch (InconsistentDebugInfoException ignored) {
         clearCaches();
         throw EvaluateExceptionUtil.INCONSISTEND_DEBUG_INFO;
       }
@@ -388,12 +396,13 @@
     try {
       return var.getVariable().isVisible(getStackFrame());
     }
-    catch (IllegalArgumentException e) {
+    catch (IllegalArgumentException ignored) {
       // can be thrown if frame's method is different than variable's method
       return false;
     }
   }
 
+  @Override
   public ClassLoaderReference getClassLoader() throws EvaluateException {
     if(myClassLoader == null) {
       myClassLoader = location().declaringType().classLoader();
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerEditorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerEditorImpl.java
index 5eb71c3..1395654 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerEditorImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerEditorImpl.java
@@ -73,8 +73,6 @@
   private final JLabel myChooseFactory = new JLabel();
   private WeakReference<ListPopup> myPopup;
 
-  private boolean myExplicitlyChosen = false;
-
   private final PsiTreeChangeListener myPsiListener = new PsiTreeChangeAdapter() {
     public void childRemoved(@NotNull PsiTreeChangeEvent event) {
       checkContext();
@@ -142,7 +140,6 @@
         @Override
         public void actionPerformed(AnActionEvent e) {
           setFactory(fragmentFactory);
-          myExplicitlyChosen = true;
           setText(getText());
           IdeFocusManager.getInstance(getProject()).requestFocus(DebuggerEditorImpl.this, true);
         }
@@ -300,33 +297,12 @@
     return DefaultCodeFragmentFactory.getInstance();
   }
 
-  @NotNull
-  private CodeFragmentFactory findFactoryForRestore(@NotNull TextWithImports text, @NotNull PsiElement context) {
-    List<CodeFragmentFactory> factories = DebuggerUtilsEx.getCodeFragmentFactories(context);
-
-    if (myExplicitlyChosen && factories.contains(myFactory)) return myFactory;
-
-    DefaultCodeFragmentFactory defaultFactory = DefaultCodeFragmentFactory.getInstance();
-    factories.remove(defaultFactory);
-    for (CodeFragmentFactory factory : factories) {
-      if (factory.getFileType().equals(text.getFileType())) {
-        return factory;
-      }
-    }
-    if (!factories.isEmpty()) return factories.get(0);
-    else return defaultFactory;
-  }
-
   protected void restoreFactory(TextWithImports text) {
     FileType fileType = text.getFileType();
     if (fileType == null) return;
     if (myContext == null) return;
 
-    CodeFragmentFactory newFactory = findFactoryForRestore(text, myContext);
-    if (!newFactory.equals(myFactory)) {
-      myExplicitlyChosen = false;
-      setFactory(newFactory);
-    }
+    setFactory(findAppropriateFactory(text, myContext));
   }
 
   private void setFactory(@NotNull final CodeFragmentFactory factory) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java
index e021d76..46f1515 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java
@@ -19,19 +19,17 @@
 import com.intellij.debugger.actions.*;
 import com.intellij.debugger.impl.DebuggerContextImpl;
 import com.intellij.debugger.settings.*;
-import com.intellij.debugger.ui.breakpoints.*;
+import com.intellij.debugger.ui.breakpoints.Breakpoint;
 import com.intellij.ide.DataManager;
 import com.intellij.openapi.Disposable;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.markup.GutterIconRenderer;
-import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.options.Configurable;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.project.ProjectManager;
-import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Key;
-import com.intellij.util.containers.ContainerUtil;
 import com.intellij.xdebugger.AbstractDebuggerSession;
 import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
 import com.intellij.xdebugger.impl.DebuggerSupport;
@@ -45,9 +43,10 @@
 import com.intellij.xdebugger.impl.settings.DebuggerSettingsPanelProvider;
 import org.jetbrains.annotations.NotNull;
 
+import javax.swing.*;
+import java.awt.*;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.List;
 
 /**
  * @author nik
@@ -63,8 +62,6 @@
   private final ForceRunToCursorActionHandler myForceRunToCursorActionHandler = new ForceRunToCursorActionHandler();
   private final ResumeActionHandler myResumeActionHandler = new ResumeActionHandler();
   private final PauseActionHandler myPauseActionHandler = new PauseActionHandler();
-  private final ToggleLineBreakpointActionHandler myToggleLineBreakpointActionHandler = new ToggleLineBreakpointActionHandler(false);
-  private final ToggleLineBreakpointActionHandler myToggleTemporaryLineBreakpointActionHandler = new ToggleLineBreakpointActionHandler(true);
   private final ShowExecutionPointActionHandler myShowExecutionPointActionHandler = new ShowExecutionPointActionHandler();
   private final EvaluateActionHandler myEvaluateActionHandler = new EvaluateActionHandler();
   private final QuickEvaluateActionHandler myQuickEvaluateHandler = new QuickEvaluateActionHandler();
@@ -73,84 +70,98 @@
   private final DebuggerActionHandler mySmartStepIntoHandler = new JvmSmartStepIntoActionHandler();
   private final DebuggerActionHandler myAddToWatchedActionHandler = new AddToWatchActionHandler();
   private final JavaMarkObjectActionHandler myMarkObjectActionHandler = new JavaMarkObjectActionHandler();
-  private final JavaEditBreakpointActionHandler myEditBreakpointActionHandler = new JavaEditBreakpointActionHandler();
 
+  @Override
   @NotNull
   public BreakpointPanelProvider<?> getBreakpointPanelProvider() {
     return myBreakpointPanelProvider;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getStepOverHandler() {
     return myStepOverActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getStepIntoHandler() {
     return myStepIntoActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getSmartStepIntoHandler() {
     return mySmartStepIntoHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getStepOutHandler() {
     return myStepOutActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getForceStepOverHandler() {
     return myForceStepOverActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getForceStepIntoHandler() {
     return myForceStepIntoActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getRunToCursorHandler() {
     return myRunToCursorActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getForceRunToCursorHandler() {
     return myForceRunToCursorActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getResumeActionHandler() {
     return myResumeActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getPauseHandler() {
     return myPauseActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getToggleLineBreakpointHandler() {
-    return myToggleLineBreakpointActionHandler;
+    return DISABLED;
   }
 
   @NotNull
   @Override
   public DebuggerActionHandler getToggleTemporaryLineBreakpointHandler() {
-    return myToggleTemporaryLineBreakpointActionHandler;
+    return DISABLED;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getShowExecutionPointHandler() {
     return myShowExecutionPointActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getEvaluateHandler() {
     return myEvaluateActionHandler;
   }
 
+  @Override
   @NotNull
   public QuickEvaluateHandler getQuickEvaluateHandler() {
     return myQuickEvaluateHandler;
@@ -162,6 +173,7 @@
     return myAddToWatchedActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerToggleActionHandler getMuteBreakpointsHandler() {
     return myMuteBreakpointsHandler;
@@ -182,134 +194,141 @@
   @NotNull
   @Override
   public EditBreakpointActionHandler getEditBreakpointAction() {
-    return myEditBreakpointActionHandler;
+    return DISABLED_EDIT;
   }
 
+  @Override
   @NotNull
   public DebuggerSettingsPanelProvider getSettingsPanelProvider() {
     return myDebuggerSettingsPanelProvider;
   }
 
   private static class JavaBreakpointPanelProvider extends BreakpointPanelProvider<Breakpoint> {
-    private final List<MyBreakpointManagerListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+    //private final List<MyBreakpointManagerListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
 
     @Override
     public AnAction[] getAddBreakpointActions(@NotNull Project project) {
-      List<AnAction> result = new ArrayList<AnAction>();
-      BreakpointFactory[] breakpointFactories = BreakpointFactory.getBreakpointFactories();
-      for (BreakpointFactory breakpointFactory : breakpointFactories) {
-        result.add(new AddJavaBreakpointAction(breakpointFactory));
-      }
-      return result.toArray(new AnAction[result.size()]);
+      //List<AnAction> result = new ArrayList<AnAction>();
+      //BreakpointFactory[] breakpointFactories = BreakpointFactory.getBreakpointFactories();
+      //for (BreakpointFactory breakpointFactory : breakpointFactories) {
+      //  result.add(new AddJavaBreakpointAction(breakpointFactory));
+      //}
+      //return result.toArray(new AnAction[result.size()]);
+      return AnAction.EMPTY_ARRAY;
     }
 
     @Override
     public void createBreakpointsGroupingRules(Collection<XBreakpointGroupingRule> rules) {
-      rules.add(new XBreakpointGroupingByCategoryRule());
+      //rules.add(new XBreakpointGroupingByCategoryRule());
       rules.add(new XBreakpointGroupingByPackageRule());
       rules.add(new XBreakpointGroupingByClassRule());
     }
 
     @Override
     public void addListener(final BreakpointsListener listener, Project project, Disposable disposable) {
-      BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager();
-      final MyBreakpointManagerListener listener1 = new MyBreakpointManagerListener(listener, breakpointManager);
-      breakpointManager.addBreakpointManagerListener(listener1);
-      myListeners.add(listener1);
-      Disposer.register(disposable, new Disposable() {
-        @Override
-        public void dispose() {
-          removeListener(listener);
-        }
-      });
+      //BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager();
+      //final MyBreakpointManagerListener listener1 = new MyBreakpointManagerListener(listener, breakpointManager);
+      //breakpointManager.addBreakpointManagerListener(listener1);
+      //myListeners.add(listener1);
+      //Disposer.register(disposable, new Disposable() {
+      //  @Override
+      //  public void dispose() {
+      //    removeListener(listener);
+      //  }
+      //});
     }
 
     @Override
     protected void removeListener(BreakpointsListener listener) {
-      for (MyBreakpointManagerListener managerListener : myListeners) {
-        if (managerListener.myListener == listener) {
-          BreakpointManager manager = managerListener.myBreakpointManager;
-          manager.removeBreakpointManagerListener(managerListener);
-          myListeners.remove(managerListener);
-          break;
-        }
-      }
+      //for (MyBreakpointManagerListener managerListener : myListeners) {
+      //  if (managerListener.myListener == listener) {
+      //    BreakpointManager manager = managerListener.myBreakpointManager;
+      //    manager.removeBreakpointManagerListener(managerListener);
+      //    myListeners.remove(managerListener);
+      //    break;
+      //  }
+      //}
     }
 
+    @Override
     public int getPriority() {
-      return 1;
+      return 100;
     }
 
+    @Override
     public Breakpoint findBreakpoint(@NotNull final Project project, @NotNull final Document document, final int offset) {
-      return DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().findBreakpoint(document, offset, null);
+      return null;
+      //return DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().findBreakpoint(document, offset, null);
     }
 
     @Override
     public GutterIconRenderer getBreakpointGutterIconRenderer(Object breakpoint) {
-      if (breakpoint instanceof BreakpointWithHighlighter) {
-        final RangeHighlighter highlighter = ((BreakpointWithHighlighter)breakpoint).getHighlighter();
-        if (highlighter != null) {
-          return (GutterIconRenderer)highlighter.getGutterIconRenderer();
-        }
-      }
+      //if (breakpoint instanceof BreakpointWithHighlighter) {
+      //  final RangeHighlighter highlighter = ((BreakpointWithHighlighter)breakpoint).getHighlighter();
+      //  if (highlighter != null) {
+      //    return (GutterIconRenderer)highlighter.getGutterIconRenderer();
+      //  }
+      //}
       return null;
     }
 
+    @Override
     public void onDialogClosed(final Project project) {
-      DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().updateAllRequests();
+      //DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().updateAllRequests();
     }
 
     @Override
     public void provideBreakpointItems(Project project, Collection<BreakpointItem> items) {
-      for (BreakpointFactory breakpointFactory : BreakpointFactory.getBreakpointFactories()) {
-        Key<? extends Breakpoint> category = breakpointFactory.getBreakpointCategory();
-        Breakpoint[] breakpoints = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getBreakpoints(category);
-        for (Breakpoint breakpoint : breakpoints) {
-          items.add(breakpointFactory.createBreakpointItem(breakpoint));
-        }
-      }
+      //for (BreakpointFactory breakpointFactory : BreakpointFactory.getBreakpointFactories()) {
+      //  Key<? extends Breakpoint> category = breakpointFactory.getBreakpointCategory();
+      //  Breakpoint[] breakpoints = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getBreakpoints(category);
+      //  for (Breakpoint breakpoint : breakpoints) {
+      //    items.add(breakpointFactory.createBreakpointItem(breakpoint));
+      //  }
+      //}
     }
 
-    private static class AddJavaBreakpointAction extends AnAction {
-      private BreakpointFactory myBreakpointFactory;
+    //private static class AddJavaBreakpointAction extends AnAction {
+    //  private BreakpointFactory myBreakpointFactory;
+    //
+    //  public AddJavaBreakpointAction(BreakpointFactory breakpointFactory) {
+    //    myBreakpointFactory = breakpointFactory;
+    //    Presentation p = getTemplatePresentation();
+    //    p.setIcon(myBreakpointFactory.getIcon());
+    //    p.setText(breakpointFactory.getDisplayName());
+    //  }
+    //
+    //  @Override
+    //  public void update(AnActionEvent e) {
+    //    e.getPresentation().setVisible(myBreakpointFactory.canAddBreakpoints());
+    //  }
+    //
+    //  @Override
+    //  public void actionPerformed(AnActionEvent e) {
+    //    myBreakpointFactory.addBreakpoint(getEventProject(e));
+    //  }
+    //}
 
-      public AddJavaBreakpointAction(BreakpointFactory breakpointFactory) {
-        myBreakpointFactory = breakpointFactory;
-        Presentation p = getTemplatePresentation();
-        p.setIcon(myBreakpointFactory.getIcon());
-        p.setText(breakpointFactory.getDisplayName());
-      }
-
-      @Override
-      public void update(AnActionEvent e) {
-        e.getPresentation().setVisible(myBreakpointFactory.canAddBreakpoints());
-      }
-
-      @Override
-      public void actionPerformed(AnActionEvent e) {
-        myBreakpointFactory.addBreakpoint(getEventProject(e));
-      }
-    }
-
-    private static class MyBreakpointManagerListener implements BreakpointManagerListener {
-
-      private final BreakpointsListener myListener;
-      public BreakpointManager myBreakpointManager;
-
-
-      public MyBreakpointManagerListener(BreakpointsListener listener, BreakpointManager breakpointManager) {
-        myListener = listener;
-        myBreakpointManager = breakpointManager;
-      }
-
-      @Override
-      public void breakpointsChanged() {
-        myListener.breakpointsChanged();
-      }
-    }
+    //private static class MyBreakpointManagerListener implements BreakpointManagerListener {
+    //
+    //  private final BreakpointsListener myListener;
+    //  public BreakpointManager myBreakpointManager;
+    //
+    //
+    //  public MyBreakpointManagerListener(BreakpointsListener listener, BreakpointManager breakpointManager) {
+    //    myListener = listener;
+    //    myBreakpointManager = breakpointManager;
+    //  }
+    //
+    //  @Override
+    //  public void breakpointsChanged() {
+    //    myListener.breakpointsChanged();
+    //  }
+    //}
   }
 
   public static class JavaDebuggerSettingsPanelProvider extends DebuggerSettingsPanelProvider {
+    @Override
     public int getPriority() {
       return 1;
     }
@@ -319,6 +338,7 @@
       return new DebuggerLaunchingConfigurable();
     }
 
+    @Override
     public Collection<? extends Configurable> getConfigurables() {
       final ArrayList<Configurable> configurables = new ArrayList<Configurable>();
       configurables.add(new DebuggerDataViewsConfigurable(null));
@@ -328,6 +348,7 @@
       return configurables;
     }
 
+    @Override
     public void apply() {
       NodeRendererSettings.getInstance().fireRenderersChanged();
     }
@@ -341,4 +362,27 @@
     }
     return ProjectManager.getInstance().getDefaultProject();
   }
+
+  private static final DebuggerActionHandler DISABLED = new DebuggerActionHandler() {
+    @Override
+    public void perform(@NotNull Project project, AnActionEvent event) {
+    }
+
+    @Override
+    public boolean isEnabled(@NotNull Project project, AnActionEvent event) {
+      return false;
+    }
+  };
+
+  private static final EditBreakpointActionHandler DISABLED_EDIT = new EditBreakpointActionHandler() {
+    @Override
+    protected void doShowPopup(Project project, JComponent component, Point whereToShow, Object breakpoint) {
+
+    }
+
+    @Override
+    public boolean isEnabled(@NotNull Project project, AnActionEvent event) {
+      return false;
+    }
+  };
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java
index e5bb8fa..dd0b0de 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java
@@ -437,7 +437,7 @@
         public void actionPerformed(AnActionEvent e) {
           if (myEventsOutOfLine.size() == 1) {
             Breakpoint breakpoint = myEventsOutOfLine.get(0).getFirst();
-            breakpoint.ENABLED = !breakpoint.ENABLED;
+            breakpoint.setEnabled(!breakpoint.isEnabled());
             DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().fireBreakpointChanged(breakpoint);
           }
         }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointCategoryGroup.java b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointCategoryGroup.java
deleted file mode 100644
index 032b480..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointCategoryGroup.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.ui;
-
-import com.intellij.debugger.ui.breakpoints.Breakpoint;
-import com.intellij.debugger.ui.breakpoints.BreakpointFactory;
-import com.intellij.openapi.util.Key;
-import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup;
-import com.intellij.xdebugger.impl.breakpoints.ui.grouping.XBreakpointTypeGroup;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-
-/**
- * Created with IntelliJ IDEA.
- * User: zajac
- * Date: 23.05.12
- * Time: 16:22
- * To change this template use File | Settings | File Templates.
- */
-public class XBreakpointCategoryGroup extends XBreakpointGroup {
-  private Key<? extends Breakpoint> myCategory;
-  private Icon myIcon;
-  private final String myName;
-
-  public XBreakpointCategoryGroup(BreakpointFactory factory) {
-    myCategory = factory.getBreakpointCategory();
-    myIcon = factory.getIcon();
-    final String name = factory.getDisplayName();
-    myName = name != null ? name : "UNKNOWN";
-  }
-
-  public Key<? extends Breakpoint> getCategory() {
-    return myCategory;
-  }
-
-  @Override
-  public Icon getIcon(boolean isOpen) {
-    return myIcon;
-  }
-
-  @NotNull
-  @Override
-  public String getName() {
-    return myName;
-  }
-
-  @Override
-  public int compareTo(XBreakpointGroup o) {
-    if (o instanceof XBreakpointTypeGroup) {
-      return -1;
-    }
-    if (o instanceof XBreakpointCategoryGroup) {
-      return getFactoryIndex() - ((XBreakpointCategoryGroup)o).getFactoryIndex();
-    }
-    return super.compareTo(o);
-  }
-
-  private int getFactoryIndex() {
-    BreakpointFactory[] breakpointFactories = BreakpointFactory.getBreakpointFactories();
-    for (int i = 0; i < breakpointFactories.length; ++i) {
-      if (breakpointFactories[i].getBreakpointCategory().equals(myCategory)) {
-        return i;
-      }
-    }
-    return -1;
-  }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByCategoryRule.java b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByCategoryRule.java
deleted file mode 100644
index f9dc88a..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByCategoryRule.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.ui;
-
-import com.intellij.debugger.ui.breakpoints.AnyExceptionBreakpoint;
-import com.intellij.debugger.ui.breakpoints.Breakpoint;
-import com.intellij.debugger.ui.breakpoints.BreakpointFactory;
-import com.intellij.debugger.ui.breakpoints.ExceptionBreakpoint;
-import com.intellij.openapi.util.Key;
-import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
-import com.intellij.xdebugger.breakpoints.ui.XBreakpointsGroupingPriorities;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-
-class XBreakpointGroupingByCategoryRule<B> extends XBreakpointGroupingRule<B, XBreakpointCategoryGroup> {
-  XBreakpointGroupingByCategoryRule() {
-    super("XBreakpointGroupingByCategoryRule", "Type");
-  }
-
-  @Override
-  public boolean isAlwaysEnabled() {
-    return true;
-  }
-
-  @Override
-  public int getPriority() {
-    return XBreakpointsGroupingPriorities.BY_TYPE;
-  }
-
-  @Override
-  public XBreakpointCategoryGroup getGroup(@NotNull B b, @NotNull Collection<XBreakpointCategoryGroup> groups) {
-    if (b instanceof Breakpoint) {
-      final Breakpoint breakpoint = (Breakpoint)b;
-      Key<? extends Breakpoint> category = breakpoint.getCategory();
-      if (category.equals(AnyExceptionBreakpoint.ANY_EXCEPTION_BREAKPOINT)) {
-        category = ExceptionBreakpoint.CATEGORY;
-      }
-      for (XBreakpointCategoryGroup group : groups) {
-        if (group.getCategory().equals(category)) {
-          return group;
-        }
-      }
-      final BreakpointFactory factory = BreakpointFactory.getInstance(category);
-      if (factory != null) {
-        return new XBreakpointCategoryGroup(factory);
-      }
-    }
-    return null;
-  }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByClassRule.java b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByClassRule.java
index f06a17e..cebaf68 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByClassRule.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByClassRule.java
@@ -15,8 +15,11 @@
  */
 package com.intellij.debugger.ui;
 
+import com.intellij.debugger.DebuggerManagerEx;
 import com.intellij.debugger.ui.breakpoints.Breakpoint;
+import com.intellij.debugger.ui.breakpoints.BreakpointManager;
 import com.intellij.icons.AllIcons;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
 import com.intellij.xdebugger.breakpoints.ui.XBreakpointsGroupingPriorities;
 import org.jetbrains.annotations.NotNull;
@@ -42,10 +45,14 @@
 
   @Override
   public XBreakpointClassGroup getGroup(@NotNull B b, @NotNull Collection<XBreakpointClassGroup> groups) {
-    if (b instanceof Breakpoint) {
-      final Breakpoint breakpoint = (Breakpoint)b;
-      String className = breakpoint.getShortClassName();
-      String packageName = breakpoint.getPackageName();
+    if (b instanceof XBreakpoint) {
+      BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(JavaDebuggerSupport.getCurrentProject()).getBreakpointManager();
+      Breakpoint javaBreakpoint = breakpointManager.findBreakpoint((XBreakpoint)b);
+      if (javaBreakpoint == null) {
+        return null;
+      }
+      String className = javaBreakpoint.getShortClassName();
+      String packageName = javaBreakpoint.getPackageName();
       if (className == null) {
         return null;
       }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java
index 5763a36..98ef5a3 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java
@@ -15,10 +15,12 @@
  */
 package com.intellij.debugger.ui;
 
-import com.intellij.debugger.ui.breakpoints.BreakpointWithHighlighter;
-import com.intellij.debugger.ui.breakpoints.ExceptionBreakpoint;
+import com.intellij.debugger.DebuggerManagerEx;
+import com.intellij.debugger.ui.breakpoints.Breakpoint;
+import com.intellij.debugger.ui.breakpoints.BreakpointManager;
 import com.intellij.icons.AllIcons;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
 import com.intellij.xdebugger.breakpoints.ui.XBreakpointsGroupingPriorities;
 import org.jetbrains.annotations.NotNull;
@@ -41,11 +43,12 @@
   @Override
   public XBreakpointPackageGroup getGroup(@NotNull B breakpoint, @NotNull Collection<XBreakpointPackageGroup> groups) {
     String packageName = null;
-    if (breakpoint instanceof BreakpointWithHighlighter) {
-      packageName = ((BreakpointWithHighlighter)breakpoint).getPackageName();
-    }
-    else if (breakpoint instanceof ExceptionBreakpoint) {
-      packageName = ((ExceptionBreakpoint)breakpoint).getPackageName();
+    if (breakpoint instanceof XBreakpoint) {
+      BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(JavaDebuggerSupport.getCurrentProject()).getBreakpointManager();
+      Breakpoint javaBreakpoint = breakpointManager.findBreakpoint((XBreakpoint)breakpoint);
+      if (javaBreakpoint != null) {
+        packageName = javaBreakpoint.getPackageName();
+      }
     }
     if (packageName == null) {
       return null;
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AddFieldBreakpointDialog.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AddFieldBreakpointDialog.java
index f325da1..e3cd522 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AddFieldBreakpointDialog.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AddFieldBreakpointDialog.java
@@ -41,7 +41,7 @@
 import java.awt.event.ActionListener;
 import java.util.List;
 
-abstract class AddFieldBreakpointDialog extends DialogWrapper {
+public abstract class AddFieldBreakpointDialog extends DialogWrapper {
   private final Project myProject;
   private JPanel myPanel;
   private TextFieldWithBrowseButton myFieldChooser;
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AddWildcardBreakpointDialog.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AddWildcardBreakpointDialog.java
index c18acb7..73c74a4 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AddWildcardBreakpointDialog.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AddWildcardBreakpointDialog.java
@@ -30,7 +30,7 @@
   private JTextField myClassPatternField;
   private JTextField myMethodNameField;
 
-  protected AddWildcardBreakpointDialog(Project project) {
+  public AddWildcardBreakpointDialog(Project project) {
     super(project, true);
     setTitle("Add Method Breakpoint");
     init();
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java
index 3d1ff85..8787290 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java
@@ -27,6 +27,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.Key;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.sun.jdi.ReferenceType;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
@@ -34,9 +35,9 @@
 public class AnyExceptionBreakpoint extends ExceptionBreakpoint {
   public static final @NonNls Key<AnyExceptionBreakpoint> ANY_EXCEPTION_BREAKPOINT = BreakpointCategory.lookup("breakpoint_any");
 
-  protected AnyExceptionBreakpoint(Project project) {
-    super(project, null, null);
-    ENABLED = false;
+  protected AnyExceptionBreakpoint(Project project, XBreakpoint xBreakpoint) {
+    super(project, null, null, xBreakpoint);
+    //setEnabled(false);
   }
 
   public Key<AnyExceptionBreakpoint> getCategory() {
@@ -49,7 +50,7 @@
 
   public void createRequest(DebugProcessImpl debugProcess) {
     DebuggerManagerThreadImpl.assertIsManagerThread();
-    if (!ENABLED || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+    if (!isEnabled() || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
       return;
     }
     super.processClassPrepare(debugProcess, null);
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java
deleted file mode 100644
index f595c1d..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.ui.breakpoints;
-
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import org.jdom.Element;
-
-import javax.swing.*;
-
-/**
- * @author Eugene Zhuravlev
- *         Date: Apr 26, 2005
- */
-public class AnyExceptionBreakpointFactory extends BreakpointFactory{
-  public Breakpoint createBreakpoint(Project project, final Element element) {
-    return new AnyExceptionBreakpoint(project);
-  }
-
-  public Icon getIcon() {
-    return AllIcons.Debugger.Db_exception_breakpoint;
-  }
-
-  public Icon getDisabledIcon() {
-    return AllIcons.Debugger.Db_disabled_exception_breakpoint;
-  }
-
-  @Override
-  protected String getHelpID() {
-    return null;  //To change body of implemented methods use File | Settings | File Templates.
-  }
-
-  @Override
-  public String getDisplayName() {
-    return null;  //To change body of implemented methods use File | Settings | File Templates.
-  }
-
-  @Override
-  public BreakpointPropertiesPanel createBreakpointPropertiesPanel(Project project, boolean compact) {
-    return new ExceptionBreakpointPropertiesPanel(project, compact);
-  }
-
-  @Override
-  public boolean breakpointCanBeRemoved(Breakpoint breakpoint) {
-    return false;
-  }
-
-  public Key<AnyExceptionBreakpoint> getBreakpointCategory() {
-    return AnyExceptionBreakpoint.ANY_EXCEPTION_BREAKPOINT;
-  }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java
index 1b370ca..bbbcf8e 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java
@@ -30,45 +30,62 @@
 import com.intellij.debugger.jdi.StackFrameProxyImpl;
 import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
 import com.intellij.debugger.requests.ClassPrepareRequestor;
+import com.intellij.debugger.settings.DebuggerSettings;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.JDOMExternalizerUtil;
 import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.WriteExternalException;
 import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
 import com.intellij.ui.AppUIUtil;
+import com.intellij.ui.classFilter.ClassFilter;
 import com.intellij.util.StringBuilderSpinAllocator;
-import com.sun.jdi.ObjectReference;
-import com.sun.jdi.ReferenceType;
-import com.sun.jdi.Value;
-import com.sun.jdi.VoidValue;
+import com.intellij.xdebugger.breakpoints.SuspendPolicy;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.sun.jdi.*;
 import com.sun.jdi.event.LocatableEvent;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;
 
 import javax.swing.*;
 import java.util.List;
 
-public abstract class Breakpoint extends FilteredRequestor implements ClassPrepareRequestor {
-  public boolean ENABLED = true;
-  public boolean LOG_ENABLED = false;
-  public boolean LOG_EXPRESSION_ENABLED = false;
-  public boolean REMOVE_AFTER_HIT = false;
-  private TextWithImports  myLogMessage; // an expression to be evaluated and printed
+public abstract class Breakpoint<P extends JavaBreakpointProperties> implements FilteredRequestor, ClassPrepareRequestor {
+  final XBreakpoint<P> myXBreakpoint;
+  protected final Project myProject;
+
+  //private boolean ENABLED = true;
+  //private boolean LOG_ENABLED = false;
+  //private boolean LOG_EXPRESSION_ENABLED = false;
+  //private boolean REMOVE_AFTER_HIT = false;
+  //private TextWithImports  myLogMessage; // an expression to be evaluated and printed
   @NonNls private static final String LOG_MESSAGE_OPTION_NAME = "LOG_MESSAGE";
   public static final Breakpoint[] EMPTY_ARRAY = new Breakpoint[0];
   protected boolean myCachedVerifiedState = false;
+  //private TextWithImportsImpl myLogMessage;
 
-  protected Breakpoint(@NotNull Project project) {
-    super(project);
-    myLogMessage = new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "");
+  protected Breakpoint(@NotNull Project project, XBreakpoint<P> xBreakpoint) {
+    //super(project);
+    myProject = project;
+    myXBreakpoint = xBreakpoint;
+    //myLogMessage = new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "");
     //noinspection AbstractMethodCallInConstructor
-    final BreakpointDefaults defaults = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getBreakpointDefaults(getCategory());
-    SUSPEND_POLICY = defaults.getSuspendPolicy();
-    CONDITION_ENABLED = defaults.isConditionEnabled();
+    //final BreakpointDefaults defaults = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getBreakpointDefaults(getCategory());
+    //SUSPEND_POLICY = defaults.getSuspendPolicy();
+    //CONDITION_ENABLED = defaults.isConditionEnabled();
+  }
+
+  public Project getProject() {
+    return myProject;
+  }
+
+  protected P getProperties() {
+    return myXBreakpoint.getProperties();
   }
 
   public abstract PsiClass getPsiClass();
@@ -100,6 +117,16 @@
     myCachedVerifiedState = isVerified;
   }
 
+  public boolean isRemoveAfterHit() {
+    return myXBreakpoint instanceof XLineBreakpoint && ((XLineBreakpoint)myXBreakpoint).isTemporary();
+  }
+
+  public void setRemoveAfterHit(boolean value) {
+    if (myXBreakpoint instanceof XLineBreakpoint) {
+      ((XLineBreakpoint)myXBreakpoint).setTemporary(value);
+    }
+  }
+
   @Nullable
   public String getShortClassName() {
     final String className = getClassName();
@@ -210,19 +237,19 @@
 
   private void runAction(final EvaluationContextImpl context, LocatableEvent event) {
     final DebugProcessImpl debugProcess = context.getDebugProcess();
-    if (LOG_ENABLED || LOG_EXPRESSION_ENABLED) {
+    if (isLogEnabled() || isLogExpressionEnabled()) {
       final StringBuilder buf = StringBuilderSpinAllocator.alloc();
       try {
-        if (LOG_ENABLED) {
+        if (myXBreakpoint.isLogMessage()) {
           buf.append(getEventMessage(event));
           buf.append("\n");
         }
-        final TextWithImports expressionToEvaluate = getLogMessage();
-        if (LOG_EXPRESSION_ENABLED && expressionToEvaluate != null && !"".equals(expressionToEvaluate.getText())) {
+        if (isLogExpressionEnabled()) {
           if(!debugProcess.isAttached()) {
             return;
           }
-  
+
+          final TextWithImports expressionToEvaluate = getLogMessage();
           try {
             ExpressionEvaluator evaluator = DebuggerInvocationUtil.commitAndRunReadAction(getProject(), new EvaluatingComputable<ExpressionEvaluator>() {
               @Override
@@ -252,11 +279,112 @@
         StringBuilderSpinAllocator.dispose(buf);
       }
     }
-    if (REMOVE_AFTER_HIT) {
+    if (isRemoveAfterHit()) {
       handleTemporaryBreakpointHit(debugProcess);
     }
   }
 
+  /**
+   * @return true if the ID was added or false otherwise
+   */
+  private boolean hasObjectID(long id) {
+    for (InstanceFilter instanceFilter : getInstanceFilters()) {
+      if (instanceFilter.getId() == id) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public boolean evaluateCondition(final EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
+    if(isCountFilterEnabled()) {
+      final DebugProcessImpl debugProcess = context.getDebugProcess();
+      debugProcess.getVirtualMachineProxy().suspend();
+      debugProcess.getRequestsManager().deleteRequest(this);
+      ((Breakpoint)this).createRequest(debugProcess);
+      debugProcess.getVirtualMachineProxy().resume();
+    }
+    if (isInstanceFiltersEnabled()) {
+      Value value = context.getThisObject();
+      if (value != null) {  // non-static
+        ObjectReference reference = (ObjectReference)value;
+        if(!hasObjectID(reference.uniqueID())) {
+          return false;
+        }
+      }
+    }
+
+    if (isClassFiltersEnabled()) {
+      String typeName = calculateEventClass(context, event);
+      if (!typeMatchesClassFilters(typeName)) return false;
+    }
+
+    if (isConditionEnabled() && !getCondition().getText().isEmpty()) {
+      try {
+        ExpressionEvaluator evaluator = DebuggerInvocationUtil.commitAndRunReadAction(context.getProject(), new EvaluatingComputable<ExpressionEvaluator>() {
+          public ExpressionEvaluator compute() throws EvaluateException {
+            final SourcePosition contextSourcePosition = ContextUtil.getSourcePosition(context);
+            // IMPORTANT: calculate context psi element basing on the location where the exception
+            // has been hit, not on the location where it was set. (For line breakpoints these locations are the same, however,
+            // for method, exception and field breakpoints these locations differ)
+            PsiElement contextPsiElement = ContextUtil.getContextElement(contextSourcePosition);
+            if (contextPsiElement == null) {
+              contextPsiElement = getEvaluationElement(); // as a last resort
+            }
+            return EvaluatorBuilderImpl.build(getCondition(), contextPsiElement, contextSourcePosition);
+          }
+        });
+        final Value value = evaluator.evaluate(context);
+        if (!(value instanceof BooleanValue)) {
+          throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.boolean.expected"));
+        }
+        if(!((BooleanValue)value).booleanValue()) {
+          return false;
+        }
+      }
+      catch (EvaluateException ex) {
+        if(ex.getCause() instanceof VMDisconnectedException) {
+          return false;
+        }
+        throw EvaluateExceptionUtil.createEvaluateException(
+          DebuggerBundle.message("error.failed.evaluating.breakpoint.condition", getCondition(), ex.getMessage())
+        );
+      }
+      return true;
+    }
+
+    return true;
+  }
+
+  protected String calculateEventClass(EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
+    return event.location().declaringType().name();
+  }
+
+  private boolean typeMatchesClassFilters(@Nullable String typeName) {
+    if (typeName == null) {
+      return true;
+    }
+    boolean matches = false, hasEnabled = false;
+    for (ClassFilter classFilter : getClassFilters()) {
+      if (classFilter.isEnabled()) {
+        hasEnabled = true;
+        if (classFilter.matches(typeName)) {
+          matches = true;
+          break;
+        }
+      }
+    }
+    if(hasEnabled && !matches) {
+      return false;
+    }
+    for (ClassFilter classFilter : getClassExclusionFilters()) {
+      if (classFilter.isEnabled() && classFilter.matches(typeName)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
   private void handleTemporaryBreakpointHit(final DebugProcessImpl debugProcess) {
     debugProcess.addDebugProcessListener(new DebugProcessAdapter() {
       @Override
@@ -288,26 +416,213 @@
     RequestManagerImpl.deleteRequests(this);
   }
 
-  @Override
   public void readExternal(Element parentNode) throws InvalidDataException {
-    super.readExternal(parentNode);
-    String logMessage = JDOMExternalizerUtil.readField(parentNode, LOG_MESSAGE_OPTION_NAME);
-    if (logMessage != null) {
-      setLogMessage(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, logMessage));
+    FilteredRequestorImpl requestor = new FilteredRequestorImpl(myProject);
+    requestor.readTo(parentNode, this);
+    try {
+      setEnabled(Boolean.valueOf(JDOMExternalizerUtil.readField(parentNode, "ENABLED")));
+    } catch (Exception e) {
+    }
+    try {
+      setLogEnabled(Boolean.valueOf(JDOMExternalizerUtil.readField(parentNode, "LOG_ENABLED")));
+    } catch (Exception e) {
+    }
+    try {
+      if (Boolean.valueOf(JDOMExternalizerUtil.readField(parentNode, "LOG_EXPRESSION_ENABLED"))) {
+        String logMessage = JDOMExternalizerUtil.readField(parentNode, LOG_MESSAGE_OPTION_NAME);
+        if (logMessage != null) {
+          setLogMessage(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, logMessage));
+        }
+      }
+    } catch (Exception e) {
+    }
+    try {
+      setRemoveAfterHit(Boolean.valueOf(JDOMExternalizerUtil.readField(parentNode, "REMOVE_AFTER_HIT")));
+    } catch (Exception e) {
     }
   }
 
+  //@Override
+  //public void writeExternal(Element parentNode) throws WriteExternalException {
+    //super.writeExternal(parentNode);
+    //JDOMExternalizerUtil.writeField(parentNode, LOG_MESSAGE_OPTION_NAME, getLogMessage().toExternalForm());
+  //}
+
+  //public void setLogMessage(TextWithImports logMessage) {
+  //  myLogMessage = logMessage;
+  //}
+
+  public abstract PsiElement getEvaluationElement();
+
+  protected TextWithImports getLogMessage() {
+    return new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, myXBreakpoint.getLogExpression());
+  }
+
+  protected TextWithImports getCondition() {
+    return new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, myXBreakpoint.getCondition());
+  }
+
+  public boolean isEnabled() {
+    return myXBreakpoint.isEnabled();
+  }
+
+  public void setEnabled(boolean enabled) {
+    myXBreakpoint.setEnabled(enabled);
+  }
+
+  protected boolean isLogEnabled() {
+    return myXBreakpoint.isLogMessage();
+  }
+
+  public void setLogEnabled(boolean logEnabled) {
+    myXBreakpoint.setLogMessage(logEnabled);
+  }
+
+  protected boolean isLogExpressionEnabled() {
+    String expression = myXBreakpoint.getLogExpression();
+    if (expression == null || expression.isEmpty()) {
+      return false;
+    }
+    return !getLogMessage().isEmpty();
+  }
+
   @Override
-  public void writeExternal(Element parentNode) throws WriteExternalException {
-    super.writeExternal(parentNode);
-    JDOMExternalizerUtil.writeField(parentNode, LOG_MESSAGE_OPTION_NAME, getLogMessage().toExternalForm());
+  public boolean isCountFilterEnabled() {
+    if (getProperties() == null) {
+      return false;
+    }
+    return getProperties().COUNT_FILTER_ENABLED;
+  }
+  public void setCountFilterEnabled(boolean enabled) {
+    getProperties().COUNT_FILTER_ENABLED = enabled;
   }
 
-  public TextWithImports getLogMessage() {
-    return myLogMessage;
+  @Override
+  public int getCountFilter() {
+    return getProperties().COUNT_FILTER;
   }
 
-  public void setLogMessage(TextWithImports logMessage) {
-    myLogMessage = logMessage;
+  public void setCountFilter(int filter) {
+    getProperties().COUNT_FILTER = filter;
+  }
+
+  @Override
+  public boolean isClassFiltersEnabled() {
+    if (getProperties() == null) {
+      return false;
+    }
+    return getProperties().CLASS_FILTERS_ENABLED;
+  }
+
+  public void setClassFiltersEnabled(boolean enabled) {
+    getProperties().CLASS_FILTERS_ENABLED = enabled;
+  }
+
+  @Override
+  public ClassFilter[] getClassFilters() {
+    return getProperties().getClassFilters();
+  }
+
+  public void setClassFilters(ClassFilter[] filters) {
+    getProperties().setClassFilters(filters);
+  }
+
+  @Override
+  public ClassFilter[] getClassExclusionFilters() {
+    return getProperties().getClassExclusionFilters();
+  }
+
+  protected void setClassExclusionFilters(ClassFilter[] filters) {
+    getProperties().setClassExclusionFilters(filters);
+  }
+
+  @Override
+  public boolean isInstanceFiltersEnabled() {
+    if (getProperties() == null) {
+      return false;
+    }
+    return getProperties().INSTANCE_FILTERS_ENABLED;
+  }
+
+  public void setInstanceFiltersEnabled(boolean enabled) {
+    getProperties().INSTANCE_FILTERS_ENABLED = enabled;
+  }
+
+  @Override
+  public InstanceFilter[] getInstanceFilters() {
+    return getProperties().getInstanceFilters();
+  }
+
+  public void setInstanceFilters(InstanceFilter[] filters) {
+    getProperties().setInstanceFilters(filters);
+  }
+
+  private static String getSuspendPolicy(XBreakpoint breakpoint) {
+    switch (breakpoint.getSuspendPolicy()) {
+      case ALL:
+        return DebuggerSettings.SUSPEND_ALL;
+      case THREAD:
+        return DebuggerSettings.SUSPEND_THREAD;
+      case NONE:
+        return DebuggerSettings.SUSPEND_NONE;
+
+      default:
+        throw new IllegalArgumentException("unknown suspend policy");
+    }
+  }
+
+  static SuspendPolicy transformSuspendPolicy(String policy) {
+    if (DebuggerSettings.SUSPEND_ALL.equals(policy)) {
+      return SuspendPolicy.ALL;
+    } else if (DebuggerSettings.SUSPEND_THREAD.equals(policy)) {
+      return SuspendPolicy.THREAD;
+    } else if (DebuggerSettings.SUSPEND_NONE.equals(policy)) {
+      return SuspendPolicy.NONE;
+    } else {
+      throw new IllegalArgumentException("unknown suspend policy");
+    }
+  }
+
+  protected boolean isSuspend() {
+    return myXBreakpoint.getSuspendPolicy() != SuspendPolicy.NONE;
+  }
+
+  @Override
+  public String getSuspendPolicy() {
+    return getSuspendPolicy(myXBreakpoint);
+  }
+
+  public void setSuspendPolicy(String policy) {
+    myXBreakpoint.setSuspendPolicy(transformSuspendPolicy(policy));
+  }
+
+  protected void setLogMessage(@Nullable TextWithImports logMessage) {
+    if (logMessage != null && !logMessage.getText().isEmpty()) {
+      myXBreakpoint.setLogExpression(logMessage.toExternalForm());
+    }
+    else {
+      myXBreakpoint.setLogExpression(null);
+    }
+  }
+
+  protected boolean isConditionEnabled() {
+    String condition = myXBreakpoint.getCondition();
+    if (condition == null || condition.isEmpty()) {
+      return false;
+    }
+    return !getCondition().isEmpty();
+  }
+
+  public void setCondition(@Nullable TextWithImports condition) {
+    if (condition != null && !condition.getText().isEmpty()) {
+      myXBreakpoint.setCondition(condition.toExternalForm());
+    }
+    else {
+      myXBreakpoint.setCondition(null);
+    }
+  }
+
+  protected void addInstanceFilter(long l) {
+    getProperties().addInstanceFilter(l);
   }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java
deleted file mode 100644
index 67c3293..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.ui.breakpoints;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointItem;
-import org.jdom.Element;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-
-/**
- * Used to deexternalize breakpoints of certain category while reading saved configuration and for creating configuration UI
- */
-public abstract class BreakpointFactory {
-  public static final ExtensionPointName<BreakpointFactory> EXTENSION_POINT_NAME =
-    ExtensionPointName.create("com.intellij.debugger.breakpointFactory");
-
-  public static BreakpointFactory[] getBreakpointFactories() {
-    return ApplicationManager.getApplication().getExtensions(EXTENSION_POINT_NAME);
-  }
-
-  public abstract Breakpoint createBreakpoint(Project project, final Element element);
-
-  public abstract Key<? extends Breakpoint> getBreakpointCategory();
-
-  public abstract Icon getIcon();
-
-  public abstract Icon getDisabledIcon();
-
-  @Nullable
-  public static BreakpointFactory getInstance(Key<? extends Breakpoint> category) {
-    final BreakpointFactory[] allFactories = getBreakpointFactories();
-    for (final BreakpointFactory factory : allFactories) {
-      if (category.equals(factory.getBreakpointCategory())) {
-        return factory;
-      }
-    }
-    return null;
-  }
-
-  protected abstract String getHelpID();
-
-  public abstract String getDisplayName();
-
-  @Nullable
-  public abstract BreakpointPropertiesPanel createBreakpointPropertiesPanel(Project project, boolean compact);
-
-  @Nullable
-  public Breakpoint addBreakpoint(Project project) {
-    return null;
-  }
-
-  public boolean canAddBreakpoints() {
-    return false;
-  }
-
-  public boolean breakpointCanBeRemoved(Breakpoint breakpoint) {
-    return true;
-  }
-
-  public BreakpointItem createBreakpointItem(final Breakpoint breakpoint) {
-    return new JavaBreakpointItem(this, breakpoint);
-  }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java
index 1bcbf3e..76c55c7 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java
@@ -20,14 +20,11 @@
  */
 package com.intellij.debugger.ui.breakpoints;
 
-import com.intellij.codeInsight.folding.impl.actions.ExpandRegionAction;
 import com.intellij.debugger.DebuggerBundle;
 import com.intellij.debugger.DebuggerInvocationUtil;
 import com.intellij.debugger.SourcePosition;
 import com.intellij.debugger.engine.BreakpointStepMethodFilter;
 import com.intellij.debugger.engine.DebugProcessImpl;
-import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
-import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
 import com.intellij.debugger.engine.requests.RequestManagerImpl;
 import com.intellij.debugger.impl.DebuggerContextImpl;
 import com.intellij.debugger.impl.DebuggerContextListener;
@@ -35,41 +32,31 @@
 import com.intellij.debugger.impl.DebuggerSession;
 import com.intellij.debugger.ui.JavaDebuggerSupport;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.EditorFactory;
-import com.intellij.openapi.editor.event.*;
 import com.intellij.openapi.editor.markup.GutterIconRenderer;
-import com.intellij.openapi.editor.markup.MarkupEditorFilterFactory;
 import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileEditor.FileEditor;
-import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.fileEditor.TextEditor;
-import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.startup.StartupManager;
 import com.intellij.openapi.ui.MessageType;
 import com.intellij.openapi.util.*;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiField;
 import com.intellij.psi.PsiFile;
 import com.intellij.util.Alarm;
 import com.intellij.util.EventDispatcher;
-import com.intellij.util.IJSwingUtilities;
-import com.intellij.util.SystemProperties;
-import com.intellij.util.containers.MultiMap;
 import com.intellij.xdebugger.XDebuggerManager;
 import com.intellij.xdebugger.XDebuggerUtil;
-import com.intellij.xdebugger.breakpoints.XBreakpointType;
+import com.intellij.xdebugger.breakpoints.*;
 import com.intellij.xdebugger.impl.DebuggerSupport;
 import com.intellij.xdebugger.impl.XDebugSessionImpl;
-import com.sun.jdi.Field;
+import com.intellij.xdebugger.impl.breakpoints.XBreakpointManagerImpl;
+import com.intellij.xdebugger.impl.breakpoints.XDependentBreakpointManager;
 import com.sun.jdi.InternalException;
-import com.sun.jdi.ObjectReference;
 import com.sun.jdi.ThreadReference;
 import com.sun.jdi.request.*;
 import gnu.trove.THashMap;
@@ -78,11 +65,9 @@
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.java.debugger.breakpoints.JavaBreakpointAdapter;
-import org.jetbrains.java.debugger.breakpoints.JavaBreakpointType;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaExceptionBreakpointProperties;
 
 import javax.swing.*;
-import java.awt.event.MouseEvent;
 import java.util.*;
 
 public class BreakpointManager {
@@ -94,15 +79,13 @@
   @NonNls private static final String DEFAULT_CONDITION_STATE_ATTRIBUTE_NAME = "default_condition_enabled";
 
   @NonNls private static final String RULES_GROUP_NAME = "breakpoint_rules";
+  private static final String CONVERTED_PARAM = "converted";
 
   private final Project myProject;
-  private AnyExceptionBreakpoint myAnyExceptionBreakpoint;
-  private final List<Breakpoint> myBreakpoints = new ArrayList<Breakpoint>(); // breakpoints storage, access should be synchronized
-  private final List<EnableBreakpointRule> myBreakpointRules = new ArrayList<EnableBreakpointRule>(); // breakpoint rules
+  private final Map<XBreakpoint, Breakpoint> myBreakpoints = new HashMap<XBreakpoint, Breakpoint>(); // breakpoints storage, access should be synchronized
   @Nullable private List<Breakpoint> myBreakpointsListForIteration = null; // another list for breakpoints iteration, unsynchronized access ok
-  private final MultiMap<Document, BreakpointWithHighlighter> myDocumentBreakpoints = MultiMap.createSmartList();
   private final Map<String, String> myUIProperties = new LinkedHashMap<String, String>();
-  private final Map<Key<? extends Breakpoint>, BreakpointDefaults> myBreakpointDefaults = new LinkedHashMap<Key<? extends Breakpoint>, BreakpointDefaults>();
+  //private final Map<Key<? extends Breakpoint>, BreakpointDefaults> myBreakpointDefaults = new LinkedHashMap<Key<? extends Breakpoint>, BreakpointDefaults>();
 
   private final EventDispatcher<BreakpointManagerListener> myDispatcher = EventDispatcher.create(BreakpointManagerListener.class);
 
@@ -155,212 +138,35 @@
         }
       }
     });
-
-    if (!project.isDefault()) {
-      XDebuggerManager.getInstance(project).getBreakpointManager().addBreakpointListener(
-        XBreakpointType.EXTENSION_POINT_NAME.findExtension(JavaBreakpointType.class), new JavaBreakpointAdapter(project), project);
-    }
   }
 
   public void init() {
-    EditorEventMulticaster eventMulticaster = EditorFactory.getInstance().getEventMulticaster();
-    eventMulticaster.addEditorMouseListener(new EditorMouseAdapter() {
-      @Nullable private EditorMouseEvent myMousePressedEvent;
-
-      @Nullable
-      private Breakpoint toggleBreakpoint(final boolean mostSuitingBreakpoint, final int line, boolean temporary) {
-        final Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor();
-        if (editor == null) {
-          return null;
-        }
-        final Document document = editor.getDocument();
-        final PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
-        if (!JavaBreakpointType.doCanPutAt(psiFile)) {
-          return null;
-        }
-
-        if (SystemProperties.getBooleanProperty("java.debugger.xBreakpoint", false) &&
-            XBreakpointType.EXTENSION_POINT_NAME.findExtension(JavaBreakpointType.class)
-              .canPutAt(psiFile.getVirtualFile(), line, myProject)) {
-          return null;
-        }
-
-        PsiDocumentManager.getInstance(myProject).commitDocument(document);
-
-        int offset = editor.getCaretModel().getOffset();
-        int editorLine = editor.getDocument().getLineNumber(offset);
-        if (editorLine != line) {
-          if (line < 0 || line >= document.getLineCount()) {
-            return null;
-          }
-          offset = editor.getDocument().getLineStartOffset(line);
-        }
-
-        ExpandRegionAction.expandRegionAtOffset(myProject, editor, offset);
-
-        Breakpoint breakpoint = findBreakpoint(document, offset, null);
-        if (breakpoint == null) {
-          boolean isInsideCompiledClass = StdFileTypes.CLASS.equals(psiFile.getFileType());
-          if (mostSuitingBreakpoint || isInsideCompiledClass) {
-            breakpoint = addFieldBreakpoint(document, offset);
-            if (breakpoint == null) {
-              breakpoint = addMethodBreakpoint(document, line);
-            }
-            if (breakpoint == null && !isInsideCompiledClass) {
-              breakpoint = addLineBreakpoint(document, line);
-            }
-          }
-          else {
-            breakpoint = addLineBreakpoint(document, line);
-
-            if (breakpoint == null) {
-              breakpoint = addMethodBreakpoint(document, line);
-            }
-          }
-
-          if (breakpoint != null) {
-            breakpoint.REMOVE_AFTER_HIT = temporary;
-            RequestManagerImpl.createRequests(breakpoint);
-          }
-          return breakpoint;
-        }
-        else {
-          removeBreakpoint(breakpoint);
-          return null;
-        }
-      }
-
-      private boolean isFromMyProject(Editor editor) {
-        FileEditor[] allEditors = FileEditorManager.getInstance(myProject).getAllEditors();
-        for (FileEditor ed : allEditors) {
-          if (!(ed instanceof TextEditor)) {
-            continue;
-          }
-          if (((TextEditor)ed).getEditor().equals(editor)) {
-            return true;
-          }
-        }
-        return false;
-      }
-
-      //mousePressed + mouseReleased is a hack to keep selection in editor when shift is pressed
+    XBreakpointManager manager = XDebuggerManager.getInstance(myProject).getBreakpointManager();
+    manager.addBreakpointListener(new XBreakpointListener() {
       @Override
-      public void mousePressed(@NotNull EditorMouseEvent e) {
-        if (MarkupEditorFilterFactory.createIsDiffFilter().avaliableIn(e.getEditor())) return;
-
-        if (e.isConsumed()) return;
-
-        if (e.getArea() == EditorMouseEventArea.LINE_MARKERS_AREA && e.getMouseEvent().isShiftDown()) {
-          myMousePressedEvent = e;
-          e.consume();
+      public void breakpointAdded(@NotNull XBreakpoint xBreakpoint) {
+        if (isJavaType(xBreakpoint)) {
+          onBreakpointAdded(xBreakpoint);
         }
       }
 
       @Override
-      public void mouseReleased(@NotNull EditorMouseEvent e) {
-        if (myMousePressedEvent != null) {
-          mouseClicked(e);
-        }
-        myMousePressedEvent = null;
+      public void breakpointRemoved(@NotNull XBreakpoint xBreakpoint) {
+        onBreakpointRemoved(xBreakpoint);
       }
 
       @Override
-      public void mouseClicked(@NotNull final EditorMouseEvent e) {
-        if (MarkupEditorFilterFactory.createIsDiffFilter().avaliableIn(e.getEditor())) return;
-
-        if (e.isConsumed()) return;
-
-        if (e.getArea() == EditorMouseEventArea.LINE_MARKERS_AREA) {
-          PsiDocumentManager.getInstance(myProject).commitAndRunReadAction(new Runnable() {
-            @Override
-            public void run() {
-              final Editor editor = e.getEditor();
-              if (!isFromMyProject(editor)) {
-                return;
-              }
-              final int line = editor.xyToLogicalPosition(e.getMouseEvent().getPoint()).line;
-              final Document document = editor.getDocument();
-              if (line < 0 || line >= document.getLineCount()) {
-                return;
-              }
-              MouseEvent event = e.getMouseEvent();
-              if (event.isPopupTrigger()) {
-                return;
-              }
-              if (event.getButton() != 1) {
-                return;
-              }
-              if (e.getMouseEvent().isControlDown() || e.getMouseEvent().isMetaDown()) {
-                return;
-              }
-
-              VirtualFile file = FileDocumentManager.getInstance().getFile(document);
-              if (file != null && XDebuggerUtil.getInstance().canPutBreakpointAt(myProject, file, line)) {
-                return;
-              }
-              e.consume();
-
-              DebuggerInvocationUtil.invokeLater(myProject, new Runnable() {
-                @Override
-                public void run() {
-                  final boolean suitingBreakpoint = e.getMouseEvent().isAltDown() && !e.getMouseEvent().isShiftDown();
-                  final boolean temporary = e.getMouseEvent().isAltDown() && e.getMouseEvent().isShiftDown();
-
-                  final Breakpoint breakpoint = toggleBreakpoint(suitingBreakpoint, line, temporary);
-
-
-                  if (!e.getMouseEvent().isAltDown() && e.getMouseEvent().isShiftDown() && breakpoint != null) {
-                    breakpoint.LOG_EXPRESSION_ENABLED = true;
-                    String selection = editor.getSelectionModel().getSelectedText();
-                    String text = selection != null ? selection : DebuggerBundle.message("breakpoint.log.message",
-                                                                                               breakpoint.getDisplayName());
-                    breakpoint.setLogMessage(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, text));
-                    breakpoint.SUSPEND = false;
-                    editBreakpoint(breakpoint, editor);
-
-
-                    //DialogWrapper dialog = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager()
-                    //  .createConfigurationDialog(breakpoint, BreakpointPropertiesPanel.CONTROL_LOG_MESSAGE);
-                    //dialog.show();
-                    //
-                    //if (!dialog.isOK()) {
-                    //  removeBreakpoint(breakpoint);
-                    //}
-                  }
-                }
-              });
-            }
-          });
+      public void breakpointChanged(@NotNull XBreakpoint xBreakpoint) {
+        Breakpoint breakpoint = myBreakpoints.get(xBreakpoint);
+        if (breakpoint != null) {
+          fireBreakpointChanged(breakpoint);
         }
       }
-    }, myProject);
+    });
+  }
 
-    eventMulticaster.addDocumentListener(new DocumentAdapter() {
-      private final Alarm myUpdateAlarm = new Alarm();
-
-      @Override
-      public void documentChanged(@NotNull final DocumentEvent e) {
-        final Document document = e.getDocument();
-        //noinspection SynchronizeOnThis
-        synchronized (BreakpointManager.this) {
-          Collection<BreakpointWithHighlighter> breakpoints = myDocumentBreakpoints.get(document);
-          if (!breakpoints.isEmpty()) {
-            myUpdateAlarm.cancelAllRequests();
-            // must create new array in order to avoid "concurrent modification" errors
-            final List<BreakpointWithHighlighter> breakpointsToUpdate = new ArrayList<BreakpointWithHighlighter>(breakpoints);
-            myUpdateAlarm.addRequest(new Runnable() {
-              @Override
-              public void run() {
-                if (!myProject.isDisposed()) {
-                  PsiDocumentManager.getInstance(myProject).commitDocument(document);
-                  update(breakpointsToUpdate);
-                }
-              }
-            }, 300, ModalityState.NON_MODAL);
-          }
-        }
-      }
-    }, myProject);
+  private XBreakpointManager getXBreakpointManager() {
+    return XDebuggerManager.getInstance(myProject).getBreakpointManager();
   }
 
   public void editBreakpoint(final Breakpoint breakpoint, final Editor editor) {
@@ -380,17 +186,34 @@
     });
   }
 
-  @NotNull
-  public BreakpointDefaults getBreakpointDefaults(Key<? extends Breakpoint> category) {
-    BreakpointDefaults defaults = myBreakpointDefaults.get(category);
-    if (defaults == null) {
-      defaults = new BreakpointDefaults();
-    }
-    return defaults;
-  }
+  //@NotNull
+  //public BreakpointDefaults getBreakpointDefaults(Key<? extends Breakpoint> category) {
+  //  BreakpointDefaults defaults = myBreakpointDefaults.get(category);
+  //  if (defaults == null) {
+  //    defaults = new BreakpointDefaults();
+  //  }
+  //  return defaults;
+  //}
 
   public void setBreakpointDefaults(Key<? extends Breakpoint> category, BreakpointDefaults defaults) {
-    myBreakpointDefaults.put(category, defaults);
+    Class typeCls = null;
+    if (LineBreakpoint.CATEGORY.toString().equals(category.toString())) {
+      typeCls = JavaLineBreakpointType.class;
+    }
+    else if (MethodBreakpoint.CATEGORY.toString().equals(category.toString())) {
+      typeCls = JavaMethodBreakpointType.class;
+    }
+    else if (FieldBreakpoint.CATEGORY.toString().equals(category.toString())) {
+      typeCls = JavaFieldBreakpointType.class;
+    }
+    else if (ExceptionBreakpoint.CATEGORY.toString().equals(category.toString())) {
+      typeCls = JavaExceptionBreakpointType.class;
+    }
+    if (typeCls != null) {
+      XBreakpointType<XBreakpoint<?>, ?> type = XDebuggerUtil.getInstance().findBreakpointType(typeCls);
+      ((XBreakpointManagerImpl)getXBreakpointManager()).getBreakpointDefaults(type).setSuspendPolicy(Breakpoint.transformSuspendPolicy(defaults.getSuspendPolicy()));
+    }
+    //myBreakpointDefaults.put(category, defaults);
   }
 
 
@@ -410,8 +233,8 @@
     if (!LineBreakpoint.canAddLineBreakpoint(myProject, document, lineIndex)) {
       return null;
     }
-
-    LineBreakpoint breakpoint = LineBreakpoint.create(myProject, document, lineIndex);
+    XLineBreakpoint xLineBreakpoint = addXLineBreakpoint(JavaLineBreakpointType.class, document, lineIndex);
+    LineBreakpoint breakpoint = LineBreakpoint.create(myProject, xLineBreakpoint);
     if (breakpoint == null) {
       return null;
     }
@@ -420,15 +243,15 @@
     return breakpoint;
   }
 
-  @Nullable
-  public FieldBreakpoint addFieldBreakpoint(Field field, ObjectReference object) {
-    ApplicationManager.getApplication().assertIsDispatchThread();
-    final FieldBreakpoint fieldBreakpoint = FieldBreakpoint.create(myProject, field, object);
-    if (fieldBreakpoint != null) {
-      addBreakpoint(fieldBreakpoint);
-    }
-    return fieldBreakpoint;
-  }
+  //@Nullable
+  //public FieldBreakpoint addFieldBreakpoint(Field field, ObjectReference object) {
+  //  ApplicationManager.getApplication().assertIsDispatchThread();
+  //  final FieldBreakpoint fieldBreakpoint = FieldBreakpoint.create(myProject, field, object, null);
+  //  if (fieldBreakpoint != null) {
+  //    addBreakpoint(fieldBreakpoint);
+  //  }
+  //  return fieldBreakpoint;
+  //}
 
   @Nullable
   public FieldBreakpoint addFieldBreakpoint(@NotNull Document document, int offset) {
@@ -449,7 +272,8 @@
   @Nullable
   public FieldBreakpoint addFieldBreakpoint(Document document, int lineIndex, String fieldName) {
     ApplicationManager.getApplication().assertIsDispatchThread();
-    FieldBreakpoint fieldBreakpoint = FieldBreakpoint.create(myProject, document, lineIndex, fieldName);
+    XLineBreakpoint xBreakpoint = addXLineBreakpoint(JavaFieldBreakpointType.class, document, lineIndex);
+    FieldBreakpoint fieldBreakpoint = FieldBreakpoint.create(myProject, fieldName, xBreakpoint);
     if (fieldBreakpoint != null) {
       addBreakpoint(fieldBreakpoint);
     }
@@ -457,21 +281,30 @@
   }
 
   @NotNull
-  public ExceptionBreakpoint addExceptionBreakpoint(@NotNull String exceptionClassName, String packageName) {
+  public ExceptionBreakpoint addExceptionBreakpoint(@NotNull final String exceptionClassName, final String packageName) {
     ApplicationManager.getApplication().assertIsDispatchThread();
-    ExceptionBreakpoint breakpoint = new ExceptionBreakpoint(myProject, exceptionClassName, packageName);
-    addBreakpoint(breakpoint);
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("ExceptionBreakpoint Added");
-    }
-    return breakpoint;
+    final JavaExceptionBreakpointType type = (JavaExceptionBreakpointType)XDebuggerUtil.getInstance().findBreakpointType(JavaExceptionBreakpointType.class);
+    return ApplicationManager.getApplication().runWriteAction(new Computable<ExceptionBreakpoint>() {
+      @Override
+      public ExceptionBreakpoint compute() {
+        XBreakpoint<JavaExceptionBreakpointProperties> xBreakpoint = XDebuggerManager.getInstance(myProject).getBreakpointManager()
+          .addBreakpoint(type, new JavaExceptionBreakpointProperties(exceptionClassName, packageName));
+        ExceptionBreakpoint breakpoint = new ExceptionBreakpoint(myProject, exceptionClassName, packageName, xBreakpoint);
+        addBreakpoint(breakpoint);
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("ExceptionBreakpoint Added");
+        }
+        return breakpoint;
+      }
+    });
   }
 
   @Nullable
   public MethodBreakpoint addMethodBreakpoint(Document document, int lineIndex) {
     ApplicationManager.getApplication().assertIsDispatchThread();
 
-    MethodBreakpoint breakpoint = MethodBreakpoint.create(myProject, document, lineIndex);
+    XLineBreakpoint xBreakpoint = addXLineBreakpoint(JavaMethodBreakpointType.class, document, lineIndex);
+    MethodBreakpoint breakpoint = MethodBreakpoint.create(myProject, xBreakpoint);
     if (breakpoint == null) {
       return null;
     }
@@ -482,10 +315,23 @@
     return breakpoint;
   }
 
+  private <B extends XBreakpoint<?>> XLineBreakpoint addXLineBreakpoint(Class<? extends XBreakpointType<B,?>> typeCls, Document document, final int lineIndex) {
+    final XBreakpointType<B, ?> type = XDebuggerUtil.getInstance().findBreakpointType(typeCls);
+    final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
+    return ApplicationManager.getApplication().runWriteAction(new Computable<XLineBreakpoint>() {
+      @Override
+      public XLineBreakpoint compute() {
+        return XDebuggerManager.getInstance(myProject).getBreakpointManager()
+          .addLineBreakpoint((XLineBreakpointType)type, file.getUrl(), lineIndex,
+                             ((XLineBreakpointType)type).createBreakpointProperties(file, lineIndex));
+      }
+    });
+  }
+
   @Nullable
   public WildcardMethodBreakpoint addMethodBreakpoint(String classPattern, String methodName) {
     ApplicationManager.getApplication().assertIsDispatchThread();
-    WildcardMethodBreakpoint breakpoint = WildcardMethodBreakpoint.create(myProject, classPattern, methodName);
+    WildcardMethodBreakpoint breakpoint = WildcardMethodBreakpoint.create(myProject, classPattern, methodName, null);
     if (breakpoint == null) {
       return null;
     }
@@ -531,14 +377,6 @@
    */
   @Nullable
   public <T extends BreakpointWithHighlighter> T findBreakpoint(final Document document, final int offset, @Nullable final Key<T> category) {
-    for (BreakpointWithHighlighter breakpointWithHighlighter : myDocumentBreakpoints.get(document)) {
-      if (breakpointWithHighlighter.isAt(document, offset) &&
-          (category == null || category.equals(breakpointWithHighlighter.getCategory()))) {
-        //noinspection unchecked
-        return (T)breakpointWithHighlighter;
-      }
-    }
-
     for (final Breakpoint breakpoint : getBreakpoints()) {
       if (breakpoint instanceof BreakpointWithHighlighter && ((BreakpointWithHighlighter)breakpoint).isAt(document, offset)) {
         if (category == null || category.equals(breakpoint.getCategory())) {
@@ -550,7 +388,17 @@
     return null;
   }
 
+  public Breakpoint findBreakpoint(XBreakpoint xBreakpoint) {
+    return myBreakpoints.get(xBreakpoint);
+  }
+
+  private List<Element> myOriginalBreakpointsNodes = new ArrayList<Element>();
+
   public void readExternal(@NotNull final Element parentNode) {
+    // save old breakpoints
+    for (Element element : parentNode.getChildren()) {
+      myOriginalBreakpointsNodes.add(element.clone());
+    }
     if (myProject.isOpen()) {
       doRead(parentNode);
     }
@@ -577,6 +425,10 @@
             if (group.getName().equals(RULES_GROUP_NAME)) {
               continue;
             }
+            // skip already converted
+            if (group.getAttribute(CONVERTED_PARAM) != null) {
+              continue;
+            }
             final String categoryName = group.getName();
             final Key<Breakpoint> breakpointCategory = BreakpointCategory.lookup(categoryName);
             final String defaultPolicy = group.getAttributeValue(DEFAULT_SUSPEND_POLICY_ATTRIBUTE_NAME);
@@ -586,16 +438,15 @@
             if (!AnyExceptionBreakpoint.ANY_EXCEPTION_BREAKPOINT.equals(breakpointCategory)) {
               // for compatibility with previous format
               anyExceptionBreakpointGroup = group.getChild(AnyExceptionBreakpoint.ANY_EXCEPTION_BREAKPOINT.toString());
-              final BreakpointFactory factory = BreakpointFactory.getInstance(breakpointCategory);
-              if (factory != null) {
-                for (final Object o : group.getChildren("breakpoint")) {
-                  Element breakpointNode = (Element)o;
-                  Breakpoint breakpoint = factory.createBreakpoint(myProject, breakpointNode);
+              //final BreakpointFactory factory = BreakpointFactory.getInstance(breakpointCategory);
+              //if (factory != null) {
+                for (Element breakpointNode : group.getChildren("breakpoint")) {
+                  //Breakpoint breakpoint = factory.createBreakpoint(myProject, breakpointNode);
+                  Breakpoint breakpoint = createBreakpoint(categoryName, breakpointNode);
                   breakpoint.readExternal(breakpointNode);
-                  addBreakpoint(breakpoint);
                   nameToBreakpointMap.put(breakpoint.getDisplayName(), breakpoint);
                 }
-              }
+              //}
             }
             else {
               anyExceptionBreakpointGroup = group;
@@ -604,10 +455,14 @@
             if (anyExceptionBreakpointGroup != null) {
               final Element breakpointElement = group.getChild("breakpoint");
               if (breakpointElement != null) {
-                getAnyExceptionBreakpoint().readExternal(breakpointElement);
+                XBreakpointManager manager = XDebuggerManager.getInstance(myProject).getBreakpointManager();
+                JavaExceptionBreakpointType type = (JavaExceptionBreakpointType)XDebuggerUtil.getInstance().findBreakpointType(JavaExceptionBreakpointType.class);
+                XBreakpoint<JavaExceptionBreakpointProperties> xBreakpoint = manager.getDefaultBreakpoint(type);
+                Breakpoint breakpoint = createJavaBreakpoint(xBreakpoint);
+                breakpoint.readExternal(breakpointElement);
+                addBreakpoint(breakpoint);
               }
             }
-
           }
         }
         catch (InvalidDataException ignored) {
@@ -615,9 +470,12 @@
 
         final Element rulesGroup = parentNode.getChild(RULES_GROUP_NAME);
         if (rulesGroup != null) {
-          final List rules = rulesGroup.getChildren("rule");
-          for (final Object rule1 : rules) {
-            final Element rule = (Element)rule1;
+          final List<Element> rules = rulesGroup.getChildren("rule");
+          for (Element rule : rules) {
+            // skip already converted
+            if (rule.getAttribute(CONVERTED_PARAM) != null) {
+              continue;
+            }
             final Element master = rule.getChild(MASTER_BREAKPOINT_TAGNAME);
             if (master == null) {
               continue;
@@ -634,7 +492,11 @@
             if (slaveBreakpoint == null) {
               continue;
             }
-            addBreakpointRule(new EnableBreakpointRule(BreakpointManager.this, masterBreakpoint, slaveBreakpoint, "true".equalsIgnoreCase(rule.getAttributeValue("leaveEnabled"))));
+
+            boolean leaveEnabled = "true".equalsIgnoreCase(rule.getAttributeValue("leaveEnabled"));
+            XDependentBreakpointManager dependentBreakpointManager = ((XBreakpointManagerImpl)getXBreakpointManager()).getDependentBreakpointManager();
+            dependentBreakpointManager.setMasterBreakpoint(slaveBreakpoint.myXBreakpoint, masterBreakpoint.myXBreakpoint, leaveEnabled);
+            //addBreakpointRule(new EnableBreakpointRule(BreakpointManager.this, masterBreakpoint, slaveBreakpoint, leaveEnabled));
           }
         }
 
@@ -662,112 +524,190 @@
     }
   }
 
-  //used in Fabrique
-  public synchronized void addBreakpoint(Breakpoint breakpoint) {
-    myBreakpoints.add(breakpoint);
-    myBreakpointsListForIteration = null;
-    if (breakpoint instanceof BreakpointWithHighlighter) {
-      BreakpointWithHighlighter breakpointWithHighlighter = (BreakpointWithHighlighter)breakpoint;
-      final Document document = breakpointWithHighlighter.getDocument();
-      if (document != null) {
-        myDocumentBreakpoints.putValue(document, breakpointWithHighlighter);
+  private Breakpoint createBreakpoint(String category, Element breakpointNode) throws InvalidDataException {
+    XBreakpoint xBreakpoint = null;
+    if (category.equals(LineBreakpoint.CATEGORY.toString())) {
+      xBreakpoint = createXLineBreakpoint(JavaLineBreakpointType.class, breakpointNode);
+    }
+    else if (category.equals(MethodBreakpoint.CATEGORY.toString())) {
+      if (breakpointNode.getAttribute("url") != null) {
+        xBreakpoint = createXLineBreakpoint(JavaMethodBreakpointType.class, breakpointNode);
+      }
+      else {
+        xBreakpoint = createXBreakpoint(JavaWildcardMethodBreakpointType.class, breakpointNode);
       }
     }
-    myDispatcher.getMulticaster().breakpointsChanged();
+    else if (category.equals(FieldBreakpoint.CATEGORY.toString())) {
+      xBreakpoint = createXLineBreakpoint(JavaFieldBreakpointType.class, breakpointNode);
+    }
+    else if (category.equals(ExceptionBreakpoint.CATEGORY.toString())) {
+      xBreakpoint =  createXBreakpoint(JavaExceptionBreakpointType.class, breakpointNode);
+    }
+    if (xBreakpoint == null) {
+      throw new IllegalStateException("Unknown breakpoint category " + category);
+    }
+    return myBreakpoints.get(xBreakpoint);
   }
 
-  public synchronized void removeBreakpoint(@Nullable final Breakpoint breakpoint) {
-    ApplicationManager.getApplication().assertIsDispatchThread();
+  private <B extends XBreakpoint<?>> XBreakpoint createXBreakpoint(Class<? extends XBreakpointType<B, ?>> typeCls,
+                                                                           Element breakpointNode) throws InvalidDataException {
+    final XBreakpointType<B, ?> type = XDebuggerUtil.getInstance().findBreakpointType(typeCls);
+    return ApplicationManager.getApplication().runWriteAction(new Computable<XBreakpoint>() {
+      @Override
+      public XBreakpoint compute() {
+      return XDebuggerManager.getInstance(myProject).getBreakpointManager()
+        .addBreakpoint((XBreakpointType)type, type.createProperties());
+    }});
+  }
+
+  private <B extends XBreakpoint<?>> XLineBreakpoint createXLineBreakpoint(Class<? extends XBreakpointType<B, ?>> typeCls,
+                                                                           Element breakpointNode) throws InvalidDataException {
+    final String url = breakpointNode.getAttributeValue("url");
+    VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
+    if (vFile == null) {
+      throw new InvalidDataException(DebuggerBundle.message("error.breakpoint.file.not.found", url));
+    }
+    final Document doc = FileDocumentManager.getInstance().getDocument(vFile);
+    if (doc == null) {
+      throw new InvalidDataException(DebuggerBundle.message("error.cannot.load.breakpoint.file", url));
+    }
+
+    final int line;
+    try {
+      //noinspection HardCodedStringLiteral
+      line = Integer.parseInt(breakpointNode.getAttributeValue("line"));
+    }
+    catch (Exception e) {
+      throw new InvalidDataException("Line number is invalid for breakpoint");
+    }
+    return addXLineBreakpoint(typeCls, doc, line);
+  }
+
+  //used in Fabrique
+  public synchronized void addBreakpoint(Breakpoint breakpoint) {
+    myBreakpoints.put(breakpoint.myXBreakpoint, breakpoint);
+    myBreakpointsListForIteration = null;
+    breakpoint.updateUI();
+    RequestManagerImpl.createRequests(breakpoint);
+    myDispatcher.getMulticaster().breakpointsChanged();
+    if (breakpoint instanceof MethodBreakpoint || breakpoint instanceof WildcardMethodBreakpoint) {
+      XDebugSessionImpl.NOTIFICATION_GROUP.createNotification("Method breakpoints may dramatically slow down debugging", MessageType.WARNING).notify(myProject);
+    }
+  }
+
+  private synchronized void onBreakpointAdded(XBreakpoint xBreakpoint) {
+    Breakpoint breakpoint = createJavaBreakpoint(xBreakpoint);
+    addBreakpoint(breakpoint);
+  }
+
+  public void removeBreakpoint(@Nullable final Breakpoint breakpoint) {
     if (breakpoint == null) {
       return;
     }
-
-    if (myBreakpoints.remove(breakpoint)) {
-      updateBreakpointRules(breakpoint);
-      myBreakpointsListForIteration = null;
-      if (breakpoint instanceof BreakpointWithHighlighter) {
-        for (Document document : myDocumentBreakpoints.keySet()) {
-          if (myDocumentBreakpoints.remove(document, (BreakpointWithHighlighter)breakpoint)) {
-            break;
-          }
-        }
+    ApplicationManager.getApplication().runWriteAction(new Runnable() {
+      @Override
+      public void run() {
+        getXBreakpointManager().removeBreakpoint(breakpoint.myXBreakpoint);
       }
+    });
+  }
+
+  private synchronized void onBreakpointRemoved(@Nullable final XBreakpoint xBreakpoint) {
+    ApplicationManager.getApplication().assertIsDispatchThread();
+    if (xBreakpoint == null) {
+      return;
+    }
+
+    Breakpoint breakpoint = myBreakpoints.remove(xBreakpoint);
+    if (breakpoint != null) {
+      //updateBreakpointRules(breakpoint);
+      myBreakpointsListForIteration = null;
       //we delete breakpoints inside release, so gutter will not fire events to deleted breakpoints
       breakpoint.delete();
 
+      RequestManagerImpl.deleteRequests(breakpoint);
       myDispatcher.getMulticaster().breakpointsChanged();
     }
   }
 
   public void writeExternal(@NotNull final Element parentNode) {
-    ApplicationManager.getApplication().runReadAction(new Runnable() {
-      @Override
-      public void run() {
-        removeInvalidBreakpoints();
-        final Map<Key<? extends Breakpoint>, Element> categoryToElementMap = new THashMap<Key<? extends Breakpoint>, Element>();
-        for (Key<? extends Breakpoint> category : myBreakpointDefaults.keySet()) {
-          final Element group = getCategoryGroupElement(categoryToElementMap, category, parentNode);
-          final BreakpointDefaults defaults = getBreakpointDefaults(category);
-          group.setAttribute(DEFAULT_SUSPEND_POLICY_ATTRIBUTE_NAME, String.valueOf(defaults.getSuspendPolicy()));
-          group.setAttribute(DEFAULT_CONDITION_STATE_ATTRIBUTE_NAME, String.valueOf(defaults.isConditionEnabled()));
-        }
-        // don't store invisible breakpoints
-        for (Breakpoint breakpoint : getBreakpoints()) {
-          if (breakpoint.isValid() &&
-              (!(breakpoint instanceof BreakpointWithHighlighter) || ((BreakpointWithHighlighter)breakpoint).isVisible())) {
-            writeBreakpoint(getCategoryGroupElement(categoryToElementMap, breakpoint.getCategory(), parentNode), breakpoint);
-          }
-        }
-        final AnyExceptionBreakpoint anyExceptionBreakpoint = getAnyExceptionBreakpoint();
-        final Element group = getCategoryGroupElement(categoryToElementMap, anyExceptionBreakpoint.getCategory(), parentNode);
-        writeBreakpoint(group, anyExceptionBreakpoint);
-
-        final Element rules = new Element(RULES_GROUP_NAME);
-        parentNode.addContent(rules);
-        for (EnableBreakpointRule myBreakpointRule : myBreakpointRules) {
-          writeRule(myBreakpointRule, rules);
-        }
+    // restore old breakpoints
+    for (Element group : myOriginalBreakpointsNodes) {
+      if (group.getAttribute(CONVERTED_PARAM) == null) {
+        group.setAttribute(CONVERTED_PARAM, "true");
       }
-    });
-
-    final Element uiProperties = new Element("ui_properties");
-    parentNode.addContent(uiProperties);
-    for (final String name : myUIProperties.keySet()) {
-      Element property = new Element("property");
-      uiProperties.addContent(property);
-      property.setAttribute("name", name);
-      property.setAttribute("value", myUIProperties.get(name));
+      group.detach();
     }
+
+    parentNode.addContent(myOriginalBreakpointsNodes);
+    //ApplicationManager.getApplication().runReadAction(new Runnable() {
+    //  @Override
+    //  public void run() {
+    //    removeInvalidBreakpoints();
+    //    final Map<Key<? extends Breakpoint>, Element> categoryToElementMap = new THashMap<Key<? extends Breakpoint>, Element>();
+    //    for (Key<? extends Breakpoint> category : myBreakpointDefaults.keySet()) {
+    //      final Element group = getCategoryGroupElement(categoryToElementMap, category, parentNode);
+    //      final BreakpointDefaults defaults = getBreakpointDefaults(category);
+    //      group.setAttribute(DEFAULT_SUSPEND_POLICY_ATTRIBUTE_NAME, String.valueOf(defaults.getSuspendPolicy()));
+    //      group.setAttribute(DEFAULT_CONDITION_STATE_ATTRIBUTE_NAME, String.valueOf(defaults.isConditionEnabled()));
+    //    }
+    //    // don't store invisible breakpoints
+    //    for (Breakpoint breakpoint : getBreakpoints()) {
+    //      if (breakpoint.isValid() &&
+    //          (!(breakpoint instanceof BreakpointWithHighlighter) || ((BreakpointWithHighlighter)breakpoint).isVisible())) {
+    //        writeBreakpoint(getCategoryGroupElement(categoryToElementMap, breakpoint.getCategory(), parentNode), breakpoint);
+    //      }
+    //    }
+    //    final AnyExceptionBreakpoint anyExceptionBreakpoint = getAnyExceptionBreakpoint();
+    //    final Element group = getCategoryGroupElement(categoryToElementMap, anyExceptionBreakpoint.getCategory(), parentNode);
+    //    writeBreakpoint(group, anyExceptionBreakpoint);
+    //
+    //    final Element rules = new Element(RULES_GROUP_NAME);
+    //    parentNode.addContent(rules);
+    //    //for (EnableBreakpointRule myBreakpointRule : myBreakpointRules) {
+    //    //  writeRule(myBreakpointRule, rules);
+    //    //}
+    //  }
+    //});
+    //
+    //final Element uiProperties = new Element("ui_properties");
+    //parentNode.addContent(uiProperties);
+    //for (final String name : myUIProperties.keySet()) {
+    //  Element property = new Element("property");
+    //  uiProperties.addContent(property);
+    //  property.setAttribute("name", name);
+    //  property.setAttribute("value", myUIProperties.get(name));
+    //}
   }
 
-  @SuppressWarnings({"HardCodedStringLiteral"})
-  private static void writeRule(@NotNull final EnableBreakpointRule enableBreakpointRule, @NotNull Element element) {
-    Element rule = new Element("rule");
-    if (enableBreakpointRule.isLeaveEnabled()) {
-      rule.setAttribute("leaveEnabled", Boolean.toString(true));
-    }
-    element.addContent(rule);
-    writeRuleBreakpoint(rule, MASTER_BREAKPOINT_TAGNAME, enableBreakpointRule.getMasterBreakpoint());
-    writeRuleBreakpoint(rule, SLAVE_BREAKPOINT_TAGNAME, enableBreakpointRule.getSlaveBreakpoint());
-  }
+  //@SuppressWarnings({"HardCodedStringLiteral"})
+  //private static void writeRule(@NotNull final EnableBreakpointRule enableBreakpointRule, @NotNull Element element) {
+  //  Element rule = new Element("rule");
+  //  if (enableBreakpointRule.isLeaveEnabled()) {
+  //    rule.setAttribute("leaveEnabled", Boolean.toString(true));
+  //  }
+  //  element.addContent(rule);
+  //  writeRuleBreakpoint(rule, MASTER_BREAKPOINT_TAGNAME, enableBreakpointRule.getMasterBreakpoint());
+  //  writeRuleBreakpoint(rule, SLAVE_BREAKPOINT_TAGNAME, enableBreakpointRule.getSlaveBreakpoint());
+  //}
 
-  @SuppressWarnings({"HardCodedStringLiteral"}) private static void writeRuleBreakpoint(@NotNull final Element element, final String tagName, @NotNull final Breakpoint breakpoint) {
-    Element master = new Element(tagName);
-    element.addContent(master);
-    master.setAttribute("name", breakpoint.getDisplayName());
-  }
+  //@SuppressWarnings({"HardCodedStringLiteral"}) private static void writeRuleBreakpoint(@NotNull final Element element, final String tagName, @NotNull final Breakpoint breakpoint) {
+  //  Element master = new Element(tagName);
+  //  element.addContent(master);
+  //  master.setAttribute("name", breakpoint.getDisplayName());
+  //}
 
-  @SuppressWarnings({"HardCodedStringLiteral"})
-  private static void writeBreakpoint(@NotNull final Element group, @NotNull final Breakpoint breakpoint) {
-    Element breakpointNode = new Element("breakpoint");
-    group.addContent(breakpointNode);
-    try {
-      breakpoint.writeExternal(breakpointNode);
-    }
-    catch (WriteExternalException e) {
-      LOG.error(e);
-    }
-  }
+  //@SuppressWarnings({"HardCodedStringLiteral"})
+  //private static void writeBreakpoint(@NotNull final Element group, @NotNull final Breakpoint breakpoint) {
+  //  Element breakpointNode = new Element("breakpoint");
+  //  group.addContent(breakpointNode);
+  //  try {
+  //    breakpoint.writeExternal(breakpointNode);
+  //  }
+  //  catch (WriteExternalException e) {
+  //    LOG.error(e);
+  //  }
+  //}
 
   private static <T extends Breakpoint> Element getCategoryGroupElement(@NotNull final Map<Key<? extends Breakpoint>, Element> categoryToElementMap, @NotNull final Key<T> category, @NotNull final Element parentNode) {
     Element group = categoryToElementMap.get(category);
@@ -814,18 +754,37 @@
   @NotNull
   public synchronized List<Breakpoint> getBreakpoints() {
     if (myBreakpointsListForIteration == null) {
-      myBreakpointsListForIteration = new ArrayList<Breakpoint>(myBreakpoints.size() + 1);
-      myBreakpointsListForIteration.addAll(myBreakpoints);
-      myBreakpointsListForIteration.add(getAnyExceptionBreakpoint());
+      myBreakpointsListForIteration = new ArrayList<Breakpoint>(myBreakpoints.size());
+
+      XBreakpoint<?>[] xBreakpoints = ApplicationManager.getApplication().runReadAction(new Computable<XBreakpoint<?>[]>() {
+        public XBreakpoint<?>[] compute() {
+          return getXBreakpointManager().getAllBreakpoints();
+        }
+      });
+      for (XBreakpoint<?> xBreakpoint : xBreakpoints) {
+        if (isJavaType(xBreakpoint)) {
+          Breakpoint breakpoint = myBreakpoints.get(xBreakpoint);
+          if (breakpoint == null) {
+            breakpoint = createJavaBreakpoint(xBreakpoint);
+            myBreakpoints.put(xBreakpoint, breakpoint);
+          }
+        }
+      }
+
+      myBreakpointsListForIteration.addAll(myBreakpoints.values());
     }
     return myBreakpointsListForIteration;
   }
 
-  public AnyExceptionBreakpoint getAnyExceptionBreakpoint() {
-    if (myAnyExceptionBreakpoint == null) {
-      myAnyExceptionBreakpoint = new AnyExceptionBreakpoint(myProject);
+  private boolean isJavaType(XBreakpoint xBreakpoint) {
+    return xBreakpoint.getType() instanceof JavaBreakpointType;
+  }
+
+  private Breakpoint createJavaBreakpoint(XBreakpoint xBreakpoint) {
+    if (xBreakpoint.getType() instanceof JavaBreakpointType) {
+      return ((JavaBreakpointType)xBreakpoint.getType()).createJavaBreakpoint(myProject, xBreakpoint);
     }
-    return myAnyExceptionBreakpoint;
+    throw new IllegalStateException("Unsupported breakpoint type:" + xBreakpoint.getType());
   }
 
   //interaction with RequestManagerImpl
@@ -963,6 +922,8 @@
   private boolean myAllowMulticasting = true;
   private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
   public void fireBreakpointChanged(Breakpoint breakpoint) {
+    breakpoint.reload();
+    breakpoint.updateUI();
     RequestManagerImpl.updateRequests(breakpoint);
     if (myAllowMulticasting) {
       // can be invoked from non-AWT thread
@@ -988,84 +949,103 @@
   }
 
   public void setBreakpointEnabled(@NotNull final Breakpoint breakpoint, final boolean enabled) {
-    if (breakpoint.ENABLED != enabled) {
-      breakpoint.ENABLED = enabled;
-      fireBreakpointChanged(breakpoint);
-      breakpoint.updateUI();
+    if (breakpoint.isEnabled() != enabled) {
+      breakpoint.setEnabled(enabled);
+      //fireBreakpointChanged(breakpoint);
+      //breakpoint.updateUI();
     }
   }
   
   public void addBreakpointRule(@NotNull EnableBreakpointRule rule) {
-    rule.init();
-    myBreakpointRules.add(rule);
+    //rule.init();
+    //myBreakpointRules.add(rule);
   }
   
   public boolean removeBreakpointRule(@NotNull EnableBreakpointRule rule) {
-    final boolean removed = myBreakpointRules.remove(rule);
-    if (removed) {
-      rule.dispose();
-    }
-    return removed;
+    //final boolean removed = myBreakpointRules.remove(rule);
+    //if (removed) {
+    //  rule.dispose();
+    //}
+    //return removed;
+    return false;
   }
   
   public boolean removeBreakpointRule(@NotNull Breakpoint slaveBreakpoint) {
-    for (final EnableBreakpointRule rule : myBreakpointRules) {
-      if (slaveBreakpoint.equals(rule.getSlaveBreakpoint())) {
-        removeBreakpointRule(rule);
-        return true;
-      }
-    }
+    //for (final EnableBreakpointRule rule : myBreakpointRules) {
+    //  if (slaveBreakpoint.equals(rule.getSlaveBreakpoint())) {
+    //    removeBreakpointRule(rule);
+    //    return true;
+    //  }
+    //}
     return false;
   }
 
-  private void updateBreakpointRules(@NotNull Breakpoint removedBreakpoint) {
-    for (Iterator<EnableBreakpointRule> it = myBreakpointRules.iterator(); it.hasNext();) {
-      final EnableBreakpointRule rule = it.next();
-      if (removedBreakpoint.equals(rule.getMasterBreakpoint()) || removedBreakpoint.equals(rule.getSlaveBreakpoint())) {
-        it.remove();
-      }
-    }
-  }
+  //private void updateBreakpointRules(@NotNull Breakpoint removedBreakpoint) {
+  //  for (Iterator<EnableBreakpointRule> it = myBreakpointRules.iterator(); it.hasNext();) {
+  //    final EnableBreakpointRule rule = it.next();
+  //    if (removedBreakpoint.equals(rule.getMasterBreakpoint()) || removedBreakpoint.equals(rule.getSlaveBreakpoint())) {
+  //      it.remove();
+  //    }
+  //  }
+  //}
 
+  // copied from XDebugSessionImpl processDependencies
   public void processBreakpointHit(@NotNull final Breakpoint breakpoint) {
-    for (final EnableBreakpointRule rule : myBreakpointRules) {
-      rule.processBreakpointHit(breakpoint);
+    XDependentBreakpointManager dependentBreakpointManager = ((XBreakpointManagerImpl)getXBreakpointManager()).getDependentBreakpointManager();
+    XBreakpoint xBreakpoint = breakpoint.myXBreakpoint;
+    if (!dependentBreakpointManager.isMasterOrSlave(xBreakpoint)) {
+      return;
+    }
+    List<XBreakpoint<?>> breakpoints = dependentBreakpointManager.getSlaveBreakpoints(xBreakpoint);
+    for (final XBreakpoint<?> slaveBreakpoint : breakpoints) {
+      DebuggerInvocationUtil.invokeLater(myProject, new Runnable() {
+        @Override
+        public void run() {
+          slaveBreakpoint.setEnabled(true);
+        }
+      });
+    }
+
+    if (dependentBreakpointManager.getMasterBreakpoint(xBreakpoint) != null && !dependentBreakpointManager.isLeaveEnabled(xBreakpoint)) {
+      DebuggerInvocationUtil.invokeLater(myProject, new Runnable() {
+        @Override
+        public void run() {
+          breakpoint.setEnabled(false);
+        }
+      });
+      //myDebuggerManager.getBreakpointManager().getLineBreakpointManager().queueBreakpointUpdate(breakpoint);
     }
   }
 
   public void setInitialBreakpointsState() {
-    myAllowMulticasting = false;
-    for (final EnableBreakpointRule myBreakpointRule : myBreakpointRules) {
-      myBreakpointRule.init();
-    }
-    myAllowMulticasting = true;
-    if (!myBreakpointRules.isEmpty()) {
-      IJSwingUtilities.invoke(new Runnable() {
-        @Override
-        public void run() {
-          myDispatcher.getMulticaster().breakpointsChanged();
-        }
-      });
-    }
+    //myAllowMulticasting = false;
+    //for (final EnableBreakpointRule myBreakpointRule : myBreakpointRules) {
+    //  myBreakpointRule.init();
+    //}
+    //myAllowMulticasting = true;
+    //if (!myBreakpointRules.isEmpty()) {
+    //  IJSwingUtilities.invoke(new Runnable() {
+    //    @Override
+    //    public void run() {
+    //      myDispatcher.getMulticaster().breakpointsChanged();
+    //    }
+    //  });
+    //}
   }
   
   @Nullable
   public Breakpoint findMasterBreakpoint(@NotNull Breakpoint dependentBreakpoint) {
-    for (final EnableBreakpointRule rule : myBreakpointRules) {
-      if (dependentBreakpoint.equals(rule.getSlaveBreakpoint())) {
-        return rule.getMasterBreakpoint();
-      }
-    }
-    return null;
+    XDependentBreakpointManager dependentBreakpointManager = ((XBreakpointManagerImpl)getXBreakpointManager()).getDependentBreakpointManager();
+    return myBreakpoints.get(dependentBreakpointManager.getMasterBreakpoint(dependentBreakpoint.myXBreakpoint));
   }
 
   @Nullable
   public EnableBreakpointRule findBreakpointRule(@NotNull Breakpoint dependentBreakpoint) {
-    for (final EnableBreakpointRule rule : myBreakpointRules) {
-      if (dependentBreakpoint.equals(rule.getSlaveBreakpoint())) {
-        return rule;
-      }
-    }
+    //for (final EnableBreakpointRule rule : myBreakpointRules) {
+    //  if (dependentBreakpoint.equals(rule.getSlaveBreakpoint())) {
+    //    return rule;
+    //  }
+    //}
     return null;
   }
 
@@ -1076,4 +1056,14 @@
   public String setProperty(String name, String value) {
     return myUIProperties.put(name, value);
   }
+
+  public static PsiFile getPsiFile(XBreakpoint xBreakpoint, Project project) {
+    try {
+      final Document document = FileDocumentManager.getInstance().getDocument(xBreakpoint.getSourcePosition().getFile());
+      return PsiDocumentManager.getInstance(project).getPsiFile(document);
+    } catch (Exception e) {
+      LOG.error(e);
+    }
+    return null;
+  }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java
index d52044b..afeeb13 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java
@@ -59,6 +59,9 @@
 import java.util.Iterator;
 import java.util.List;
 
+/*
+ * Not used any more, since move to xBreakpoints
+ */
 public abstract class BreakpointPropertiesPanel {
 
   private BreakpointChooser myMasterBreakpointChooser;
@@ -208,8 +211,8 @@
     final ItemListener suspendPolicyChangeListener = new ItemListener() {
       @Override
       public void itemStateChanged(final ItemEvent e) {
-        final BreakpointDefaults defaults = getBreakpointManager(myProject).getBreakpointDefaults(breakpointCategory);
-        myMakeDefaultButton.setEnabled(!defaults.getSuspendPolicy().equals(getSelectedSuspendPolicy()) || defaults.isConditionEnabled() != myConditionCheckbox.isSelected());
+        //final BreakpointDefaults defaults = getBreakpointManager(myProject).getBreakpointDefaults(breakpointCategory);
+        //myMakeDefaultButton.setEnabled(!defaults.getSuspendPolicy().equals(getSelectedSuspendPolicy()) || defaults.isConditionEnabled() != myConditionCheckbox.isSelected());
       }
     };
 
@@ -426,13 +429,13 @@
   }
 
   private void updateSuspendPolicyRbFont() {
-    final String defPolicy = getBreakpointManager(myProject).getBreakpointDefaults(myBreakpointCategory).getSuspendPolicy();
+    //final String defPolicy = getBreakpointManager(myProject).getBreakpointDefaults(myBreakpointCategory).getSuspendPolicy();
     
     final Font font = myRbSuspendAll.getFont().deriveFont(Font.PLAIN);
     final Font boldFont = font.deriveFont(Font.BOLD);
     
-    myRbSuspendAll.setFont(DebuggerSettings.SUSPEND_ALL.equals(defPolicy)? boldFont : font);
-    myRbSuspendThread.setFont(DebuggerSettings.SUSPEND_THREAD.equals(defPolicy)? boldFont : font);
+    //myRbSuspendAll.setFont(DebuggerSettings.SUSPEND_ALL.equals(defPolicy)? boldFont : font);
+    //myRbSuspendThread.setFont(DebuggerSettings.SUSPEND_THREAD.equals(defPolicy)? boldFont : font);
   }
 
   protected ClassFilter createClassConditionFilter() {
@@ -459,125 +462,126 @@
    * Init UI components with the values from Breakpoint
    */
   public void initFrom(Breakpoint breakpoint, boolean moreOptionsVisible1) {
-    myBreakpoint = breakpoint;
-    boolean moreOptionsVisible = moreOptionsVisible1;
-    boolean actionsPanelVisible = moreOptionsVisible1;
-
-    initMasterBreakpointPanel();
-
-    if (breakpoint.COUNT_FILTER > 0) {
-      myPassCountField.setText(Integer.toString(breakpoint.COUNT_FILTER));
-      moreOptionsVisible = true;
-    }
-    else {
-      myPassCountField.setText("");
-    }
-
-    PsiElement context = breakpoint.getEvaluationElement();
-    myPassCountCheckbox.setSelected(breakpoint.COUNT_FILTER_ENABLED);
-
-    myConditionCheckbox.setSelected(breakpoint.CONDITION_ENABLED);
-
-    myConditionCombo.setEnabled(breakpoint.CONDITION_ENABLED);
-
-    myConditionCombo.setContext(context);
-    myConditionCombo.setText(breakpoint.getCondition() != null ? breakpoint.getCondition() : emptyText());
-
-    myCbSuspend.setSelected(breakpoint.SUSPEND);
-    myRbSuspendThread.setEnabled(myCbSuspend.isSelected());
-    myRbSuspendAll.setEnabled(myCbSuspend.isSelected());
-
-    if(!breakpoint.SUSPEND) {
-      actionsPanelVisible = true;
-    }
-    if(DebuggerSettings.SUSPEND_THREAD.equals(breakpoint.SUSPEND_POLICY)){
-      myRbSuspendThread.setSelected(true);
-    }
-    else {
-      myRbSuspendAll.setSelected(true);
-    }
-
-    myCbSuspend.addActionListener(new ActionListener() {
-      @Override
-      public void actionPerformed(ActionEvent event) {
-        if (!myActionsPanel.isVisible()) {
-          if (!myCbSuspend.isSelected()) {
-            if (myDelegate != null) {
-              myDelegate.showActionsPanel();
-            }
-          }
-        }
-        myRbSuspendThread.setEnabled(myCbSuspend.isSelected());
-        myRbSuspendAll.setEnabled(myCbSuspend.isSelected());
-      }
-    });
-    myLogMessageCheckBox.setSelected(breakpoint.LOG_ENABLED);
-    myTemporaryCheckBox.setSelected(breakpoint.REMOVE_AFTER_HIT);
-    myEnabledCheckbox.setSelected(breakpoint.ENABLED);
-    myEnabledCheckbox.setText(breakpoint.getShortName() + " enabled");
-
-    DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().addBreakpointManagerListener(new BreakpointManagerListener() {
-      @Override
-      public void breakpointsChanged() {
-        myEnabledCheckbox.setSelected(myBreakpoint.ENABLED);
-      }
-    });
-
-    myEnabledCheckbox.addActionListener(new ActionListener() {
-      @Override
-      public void actionPerformed(ActionEvent event) {
-        if (myBreakpoint.ENABLED != myEnabledCheckbox.isSelected()) {
-          myBreakpoint.ENABLED = myEnabledCheckbox.isSelected();
-          getBreakpointManager(myProject).fireBreakpointChanged(myBreakpoint);
-          myBreakpoint.updateUI();
-        }
-      }
-    });
-    myTemporaryCheckBox.setVisible(breakpoint instanceof LineBreakpoint);
-    myLogExpressionCheckBox.setSelected(breakpoint.LOG_EXPRESSION_ENABLED);
-    if (breakpoint.LOG_ENABLED || breakpoint.LOG_EXPRESSION_ENABLED || (breakpoint instanceof LineBreakpoint && breakpoint.REMOVE_AFTER_HIT)) {
-      actionsPanelVisible = true;
-    }
-
-    myLogExpressionCombo.setContext(context);
-
-    if (breakpoint.getLogMessage() != null) {
-      myLogExpressionCombo.setText(breakpoint.getLogMessage());
-    }
-    else {
-      myLogExpressionCombo.setText(emptyText());
-    }
-
-    myLogExpressionCombo.setEnabled(breakpoint.LOG_EXPRESSION_ENABLED);
-    if (breakpoint.LOG_EXPRESSION_ENABLED) {
-      actionsPanelVisible = true;
-    }
-
-    myInstanceFiltersCheckBox.setSelected(breakpoint.INSTANCE_FILTERS_ENABLED);
-    myInstanceFiltersField.setEnabled(breakpoint.INSTANCE_FILTERS_ENABLED);
-    myInstanceFiltersField.getTextField().setEditable(breakpoint.INSTANCE_FILTERS_ENABLED);
-    myInstanceFilters = breakpoint.getInstanceFilters();
-    updateInstanceFilterEditor(true);
-    if (breakpoint.INSTANCE_FILTERS_ENABLED) {
-      moreOptionsVisible = true;
-    }
-
-    myClassFiltersCheckBox.setSelected(breakpoint.CLASS_FILTERS_ENABLED);
-    myClassFiltersField.setEnabled(breakpoint.CLASS_FILTERS_ENABLED);
-    myClassFiltersField.getTextField().setEditable(breakpoint.CLASS_FILTERS_ENABLED);
-    myClassFilters = breakpoint.getClassFilters();
-    myClassExclusionFilters = breakpoint.getClassExclusionFilters();
-    updateClassFilterEditor(true);
-    if (breakpoint.CLASS_FILTERS_ENABLED) {
-      moreOptionsVisible = true;
-    }
-
-    myBreakpointPsiClass = breakpoint.getPsiClass();
-
-    updateCheckboxes();
-
-    setActionsPanelVisible(actionsPanelVisible && !moreOptionsVisible1);
-    setMoreOptionsVisible(moreOptionsVisible);
+    //myBreakpoint = breakpoint;
+    //boolean moreOptionsVisible = moreOptionsVisible1;
+    //boolean actionsPanelVisible = moreOptionsVisible1;
+    //
+    //initMasterBreakpointPanel();
+    //
+    //if (breakpoint.getCountFilter() > 0) {
+    //  myPassCountField.setText(Integer.toString(breakpoint.getCountFilter()));
+    //  moreOptionsVisible = true;
+    //}
+    //else {
+    //  myPassCountField.setText("");
+    //}
+    //
+    //PsiElement context = breakpoint.getEvaluationElement();
+    //myPassCountCheckbox.setSelected(breakpoint.isCountFilterEnabled());
+    //
+    //myConditionCheckbox.setSelected(breakpoint.isConditionEnabled());
+    //
+    //myConditionCombo.setEnabled(breakpoint.isConditionEnabled());
+    //
+    //myConditionCombo.setContext(context);
+    //myConditionCombo.setText(breakpoint.getCondition() != null ? breakpoint.getCondition() : emptyText());
+    //
+    //myCbSuspend.setSelected(breakpoint.isSuspend());
+    //myRbSuspendThread.setEnabled(myCbSuspend.isSelected());
+    //myRbSuspendAll.setEnabled(myCbSuspend.isSelected());
+    //
+    //if(!breakpoint.isSuspend()) {
+    //  actionsPanelVisible = true;
+    //}
+    //if(DebuggerSettings.SUSPEND_THREAD.equals(breakpoint.getSuspendPolicy())){
+    //  myRbSuspendThread.setSelected(true);
+    //}
+    //else {
+    //  myRbSuspendAll.setSelected(true);
+    //}
+    //
+    //myCbSuspend.addActionListener(new ActionListener() {
+    //  @Override
+    //  public void actionPerformed(ActionEvent event) {
+    //    if (!myActionsPanel.isVisible()) {
+    //      if (!myCbSuspend.isSelected()) {
+    //        if (myDelegate != null) {
+    //          myDelegate.showActionsPanel();
+    //        }
+    //      }
+    //    }
+    //    myRbSuspendThread.setEnabled(myCbSuspend.isSelected());
+    //    myRbSuspendAll.setEnabled(myCbSuspend.isSelected());
+    //  }
+    //});
+    //myLogMessageCheckBox.setSelected(breakpoint.isLogEnabled());
+    //myTemporaryCheckBox.setSelected(breakpoint.isRemoveAfterHit());
+    //myEnabledCheckbox.setSelected(breakpoint.isEnabled());
+    //myEnabledCheckbox.setText(breakpoint.getShortName() + " enabled");
+    //
+    //DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().addBreakpointManagerListener(new BreakpointManagerListener() {
+    //  @Override
+    //  public void breakpointsChanged() {
+    //    myEnabledCheckbox.setSelected(myBreakpoint.isEnabled());
+    //  }
+    //});
+    //
+    //myEnabledCheckbox.addActionListener(new ActionListener() {
+    //  @Override
+    //  public void actionPerformed(ActionEvent event) {
+    //    if (myBreakpoint.isEnabled() != myEnabledCheckbox.isSelected()) {
+    //      myBreakpoint.setEnabled(myEnabledCheckbox.isSelected());
+    //      getBreakpointManager(myProject).fireBreakpointChanged(myBreakpoint);
+    //      myBreakpoint.updateUI();
+    //    }
+    //  }
+    //});
+    //myTemporaryCheckBox.setVisible(breakpoint instanceof LineBreakpoint);
+    //myLogExpressionCheckBox.setSelected(breakpoint.isLogExpressionEnabled());
+    //if (breakpoint.isLogEnabled() ||
+    //    breakpoint.isLogExpressionEnabled() || (breakpoint instanceof LineBreakpoint && breakpoint.isRemoveAfterHit())) {
+    //  actionsPanelVisible = true;
+    //}
+    //
+    //myLogExpressionCombo.setContext(context);
+    //
+    //if (breakpoint.getLogMessage() != null) {
+    //  myLogExpressionCombo.setText(breakpoint.getLogMessage());
+    //}
+    //else {
+    //  myLogExpressionCombo.setText(emptyText());
+    //}
+    //
+    //myLogExpressionCombo.setEnabled(breakpoint.isLogExpressionEnabled());
+    //if (breakpoint.isLogExpressionEnabled()) {
+    //  actionsPanelVisible = true;
+    //}
+    //
+    //myInstanceFiltersCheckBox.setSelected(breakpoint.isInstanceFiltersEnabled());
+    //myInstanceFiltersField.setEnabled(breakpoint.isInstanceFiltersEnabled());
+    //myInstanceFiltersField.getTextField().setEditable(breakpoint.isInstanceFiltersEnabled());
+    //myInstanceFilters = breakpoint.getInstanceFilters();
+    //updateInstanceFilterEditor(true);
+    //if (breakpoint.isInstanceFiltersEnabled()) {
+    //  moreOptionsVisible = true;
+    //}
+    //
+    //myClassFiltersCheckBox.setSelected(breakpoint.isClassFiltersEnabled());
+    //myClassFiltersField.setEnabled(breakpoint.isClassFiltersEnabled());
+    //myClassFiltersField.getTextField().setEditable(breakpoint.isClassFiltersEnabled());
+    //myClassFilters = breakpoint.getClassFilters();
+    //myClassExclusionFilters = breakpoint.getClassExclusionFilters();
+    //updateClassFilterEditor(true);
+    //if (breakpoint.isClassFiltersEnabled()) {
+    //  moreOptionsVisible = true;
+    //}
+    //
+    //myBreakpointPsiClass = breakpoint.getPsiClass();
+    //
+    //updateCheckboxes();
+    //
+    //setActionsPanelVisible(actionsPanelVisible && !moreOptionsVisible1);
+    //setMoreOptionsVisible(moreOptionsVisible);
   }
 
   private void initMasterBreakpointPanel() {
@@ -632,41 +636,41 @@
    */
   public void saveTo(Breakpoint breakpoint) {
 
-    saveMasterBreakpoint();
-    try {
-      String text = myPassCountField.getText().trim();
-      breakpoint.COUNT_FILTER = !text.isEmpty() ? Integer.parseInt(text) : 0;
-      if (breakpoint.COUNT_FILTER < 0) {
-        breakpoint.COUNT_FILTER = 0;
-      }
-    }
-    catch (Exception ignored) {
-    }
-
-    breakpoint.COUNT_FILTER_ENABLED = breakpoint.COUNT_FILTER > 0 && myPassCountCheckbox.isSelected();
-    breakpoint.setCondition(myConditionCombo.getText());
-    breakpoint.CONDITION_ENABLED = myConditionCheckbox.isSelected();
-    breakpoint.setLogMessage(myLogExpressionCombo.getText());
-    breakpoint.LOG_EXPRESSION_ENABLED = !breakpoint.getLogMessage().isEmpty() && myLogExpressionCheckBox.isSelected();
-    breakpoint.LOG_ENABLED = myLogMessageCheckBox.isSelected();
-    breakpoint.ENABLED = myEnabledCheckbox.isSelected();
-    breakpoint.REMOVE_AFTER_HIT = myTemporaryCheckBox.isSelected();
-    breakpoint.SUSPEND = myCbSuspend.isSelected();
-    breakpoint.SUSPEND_POLICY = getSelectedSuspendPolicy();
-    reloadInstanceFilters();
-    reloadClassFilters();
-    updateInstanceFilterEditor(true);
-    updateClassFilterEditor(true);
-
-    breakpoint.INSTANCE_FILTERS_ENABLED = myInstanceFiltersField.getText().length() > 0 && myInstanceFiltersCheckBox.isSelected();
-    breakpoint.CLASS_FILTERS_ENABLED = myClassFiltersField.getText().length() > 0 && myClassFiltersCheckBox.isSelected();
-    breakpoint.setClassFilters(myClassFilters);
-    breakpoint.setClassExclusionFilters(myClassExclusionFilters);
-    breakpoint.setInstanceFilters(myInstanceFilters);
-
-    myConditionCombo.addRecent(myConditionCombo.getText());
-    myLogExpressionCombo.addRecent(myLogExpressionCombo.getText());
-    breakpoint.updateUI();
+    //saveMasterBreakpoint();
+    //try {
+    //  String text = myPassCountField.getText().trim();
+    //  breakpoint.setCountFilter(!text.isEmpty() ? Integer.parseInt(text) : 0);
+    //  if (breakpoint.getCountFilter() < 0) {
+    //    breakpoint.setCountFilter(0);
+    //  }
+    //}
+    //catch (Exception ignored) {
+    //}
+    //
+    //breakpoint.setCountFilterEnabled(breakpoint.getCountFilter() > 0 && myPassCountCheckbox.isSelected());
+    //breakpoint.setCondition(myConditionCombo.getText().getText());
+    ////breakpoint.setConditionEnabled(myConditionCheckbox.isSelected());
+    //breakpoint.setLogMessage(myLogExpressionCombo.getText());
+    //breakpoint.setLogExpressionEnabled(!breakpoint.getLogMessage().isEmpty() && myLogExpressionCheckBox.isSelected());
+    //breakpoint.setLogEnabled(myLogMessageCheckBox.isSelected());
+    //breakpoint.setEnabled(myEnabledCheckbox.isSelected());
+    //breakpoint.setRemoveAfterHit(myTemporaryCheckBox.isSelected());
+    ////breakpoint.setSuspend(myCbSuspend.isSelected());
+    //breakpoint.setSuspendPolicy(getSelectedSuspendPolicy());
+    //reloadInstanceFilters();
+    //reloadClassFilters();
+    //updateInstanceFilterEditor(true);
+    //updateClassFilterEditor(true);
+    //
+    //breakpoint.setInstanceFiltersEnabled(myInstanceFiltersField.getText().length() > 0 && myInstanceFiltersCheckBox.isSelected());
+    //breakpoint.setClassFiltersEnabled(myClassFiltersField.getText().length() > 0 && myClassFiltersCheckBox.isSelected());
+    //breakpoint.setClassFilters(myClassFilters);
+    //breakpoint.setClassExclusionFilters(myClassExclusionFilters);
+    //breakpoint.setInstanceFilters(myInstanceFilters);
+    //
+    //myConditionCombo.addRecent(myConditionCombo.getText());
+    //myLogExpressionCombo.addRecent(myLogExpressionCombo.getText());
+    //breakpoint.updateUI();
   }
 
   private static String concatWithEx(List<String> s, String concator, int N, String NthConcator) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java
index 16b7527..8cd1bfb 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java
@@ -25,49 +25,49 @@
 import com.intellij.debugger.engine.requests.RequestManagerImpl;
 import com.intellij.debugger.impl.DebuggerContextImpl;
 import com.intellij.debugger.settings.DebuggerSettings;
-import com.intellij.debugger.ui.JavaDebuggerSupport;
-import com.intellij.openapi.actionSystem.ActionGroup;
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.ex.MarkupModelEx;
 import com.intellij.openapi.editor.impl.DocumentMarkupModel;
-import com.intellij.openapi.editor.markup.*;
+import com.intellij.openapi.editor.markup.MarkupEditorFilterFactory;
+import com.intellij.openapi.editor.markup.RangeHighlighter;
+import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.Key;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiManager;
 import com.intellij.psi.jsp.JspFile;
-import com.intellij.ui.AppUIUtil;
 import com.intellij.ui.classFilter.ClassFilter;
 import com.intellij.util.StringBuilderSpinAllocator;
-import com.intellij.xdebugger.impl.DebuggerSupport;
-import com.intellij.xdebugger.impl.actions.EditBreakpointAction;
+import com.intellij.xdebugger.XDebuggerManager;
+import com.intellij.xdebugger.XSourcePosition;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.XBreakpointManager;
+import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
 import com.intellij.xdebugger.ui.DebuggerColors;
 import com.intellij.xml.util.XmlStringUtil;
 import com.sun.jdi.ReferenceType;
 import org.jdom.Element;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;
 
 import javax.swing.*;
-import java.awt.*;
-import java.awt.dnd.DragSource;
 
 /**
  * User: lex
  * Date: Sep 2, 2003
  * Time: 3:22:55 PM
  */
-public abstract class BreakpointWithHighlighter extends Breakpoint {
+public abstract class BreakpointWithHighlighter<P extends JavaBreakpointProperties> extends Breakpoint<P> {
   @Nullable
   private RangeHighlighter myHighlighter;
 
@@ -150,7 +150,7 @@
 
   private Icon calcIcon(@Nullable DebugProcessImpl debugProcess) {
     final boolean muted = debugProcess != null && isMuted(debugProcess);
-    if (!ENABLED) {
+    if (!isEnabled()) {
       return getDisabledIcon(muted);
     }
 
@@ -184,13 +184,14 @@
     return getSetIcon(muted);
   }
 
-  protected BreakpointWithHighlighter(@NotNull Project project) {
+  protected BreakpointWithHighlighter(@NotNull Project project, XBreakpoint xBreakpoint) {
     //for persistency
-    super(project);
+    super(project, xBreakpoint);
+    reload();
   }
 
-  public BreakpointWithHighlighter(@NotNull final Project project, @NotNull final RangeHighlighter highlighter) {
-    super(project);
+  public BreakpointWithHighlighter(@NotNull final Project project, @NotNull final RangeHighlighter highlighter, XBreakpoint breakpoint) {
+    super(project, breakpoint);
     myHighlighter = highlighter;
     setEditorFilter(highlighter);
     reload();
@@ -208,10 +209,10 @@
 
   @Override
   public boolean isValid() {
-    return isPositionValid(getSourcePosition());
+    return isPositionValid(myXBreakpoint.getSourcePosition());
   }
 
-  private static boolean isPositionValid(@Nullable final SourcePosition sourcePosition) {
+  protected static boolean isPositionValid(@Nullable final XSourcePosition sourcePosition) {
     return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
       @Override
       public Boolean compute() {
@@ -238,34 +239,34 @@
       }
       buf.append("&nbsp;<br>&nbsp;");
       buf.append(DebuggerBundle.message("breakpoint.property.name.suspend.policy")).append(" : ");
-      if (DebuggerSettings.SUSPEND_NONE.equals(SUSPEND_POLICY) || !SUSPEND) {
+      if (DebuggerSettings.SUSPEND_NONE.equals(getSuspendPolicy()) || !isSuspend()) {
         buf.append(DebuggerBundle.message("breakpoint.properties.panel.option.suspend.none"));
       }
-      else if (DebuggerSettings.SUSPEND_ALL.equals(SUSPEND_POLICY)) {
+      else if (DebuggerSettings.SUSPEND_ALL.equals(getSuspendPolicy())) {
         buf.append(DebuggerBundle.message("breakpoint.properties.panel.option.suspend.all"));
       }
-      else if (DebuggerSettings.SUSPEND_THREAD.equals(SUSPEND_POLICY)) {
+      else if (DebuggerSettings.SUSPEND_THREAD.equals(getSuspendPolicy())) {
         buf.append(DebuggerBundle.message("breakpoint.properties.panel.option.suspend.thread"));
       }
       buf.append("&nbsp;<br>&nbsp;");
       buf.append(DebuggerBundle.message("breakpoint.property.name.log.message")).append(": ");
-      buf.append(LOG_ENABLED ? CommonBundle.getYesButtonText() : CommonBundle.getNoButtonText());
-      if (LOG_EXPRESSION_ENABLED) {
+      buf.append(isLogEnabled() ? CommonBundle.getYesButtonText() : CommonBundle.getNoButtonText());
+      if (isLogExpressionEnabled()) {
         buf.append("&nbsp;<br>&nbsp;");
         buf.append(DebuggerBundle.message("breakpoint.property.name.log.expression")).append(": ");
         buf.append(XmlStringUtil.escapeString(getLogMessage().getText()));
       }
-      if (CONDITION_ENABLED && getCondition() != null && getCondition().getText() != null && !getCondition().getText().isEmpty()) {
+      if (isConditionEnabled() && getCondition() != null && getCondition().getText() != null && !getCondition().getText().isEmpty()) {
         buf.append("&nbsp;<br>&nbsp;");
         buf.append(DebuggerBundle.message("breakpoint.property.name.condition")).append(": ");
         buf.append(XmlStringUtil.escapeString(getCondition().getText()));
       }
-      if (COUNT_FILTER_ENABLED) {
+      if (isCountFilterEnabled()) {
         buf.append("&nbsp;<br>&nbsp;");
         buf.append(DebuggerBundle.message("breakpoint.property.name.pass.count")).append(": ");
-        buf.append(COUNT_FILTER);
+        buf.append(getCountFilter());
       }
-      if (CLASS_FILTERS_ENABLED) {
+      if (isClassFiltersEnabled()) {
         buf.append("&nbsp;<br>&nbsp;");
         buf.append(DebuggerBundle.message("breakpoint.property.name.class.filters")).append(": ");
         ClassFilter[] classFilters = getClassFilters();
@@ -273,7 +274,7 @@
           buf.append(classFilter.getPattern()).append(" ");
         }
       }
-      if (INSTANCE_FILTERS_ENABLED) {
+      if (isInstanceFiltersEnabled()) {
         buf.append("&nbsp;<br>&nbsp;");
         buf.append(DebuggerBundle.message("breakpoint.property.name.instance.filters"));
         InstanceFilter[] instanceFilters = getInstanceFilters();
@@ -290,25 +291,23 @@
   }
 
   @Override
-  public final void reload() {
+  public void reload() {
     ApplicationManager.getApplication().assertReadAccessAllowed();
-    RangeHighlighter highlighter = myHighlighter;
-    if (highlighter != null && highlighter.isValid()) {
-      PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(highlighter.getDocument());
-      if (psiFile != null) {
-        mySourcePosition = SourcePosition.createFromOffset(psiFile, highlighter.getStartOffset());
-        reload(psiFile);
-        return;
-      }
+    final XSourcePosition position = myXBreakpoint.getSourcePosition();
+    try {
+      final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(position.getFile());
+      mySourcePosition = SourcePosition.createFromOffset(psiFile, position.getOffset());
+    } catch (Exception e) {
+      mySourcePosition = null;
     }
-    mySourcePosition = null;
+    reload(BreakpointManager.getPsiFile(myXBreakpoint, myProject));
   }
 
   @Override
   public void createRequest(@NotNull DebugProcessImpl debugProcess) {
     DebuggerManagerThreadImpl.assertIsManagerThread();
     // check is this breakpoint is enabled, vm reference is valid and there're no requests created yet
-    if (!ENABLED ||
+    if (!isEnabled() ||
         !debugProcess.isAttached() ||
         isMuted(debugProcess) ||
         !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
@@ -329,7 +328,7 @@
 
   @Override
   public void processClassPrepare(final DebugProcess debugProcess, final ReferenceType classType) {
-    if (!ENABLED || !isValid()) {
+    if (!isEnabled() || !isValid()) {
       return;
     }
     createRequestForPreparedClass((DebugProcessImpl)debugProcess, classType);
@@ -383,20 +382,24 @@
 
   private void updateGutter() {
     if (myVisible) {
-      RangeHighlighter highlighter = myHighlighter;
-      if (highlighter != null && highlighter.isValid() && isValid()) {
-        AppUIUtil.invokeLaterIfProjectAlive(myProject, new Runnable() {
-          @Override
-          public void run() {
-            if (isValid()) {
-              setupGutterRenderer(myHighlighter);
-            }
-          }
-        });
+      if (isValid()) {
+        final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(myProject).getBreakpointManager();
+        breakpointManager.updateBreakpointPresentation((XLineBreakpoint)myXBreakpoint, getIcon(), null);
       }
-      else {
-        DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().removeBreakpoint(this);
-      }
+      //RangeHighlighter highlighter = myHighlighter;
+      //if (highlighter != null && highlighter.isValid() && isValid()) {
+      //  AppUIUtil.invokeLaterIfProjectAlive(myProject, new Runnable() {
+      //    @Override
+      //    public void run() {
+      //      if (isValid()) {
+      //        setupGutterRenderer(myHighlighter);
+      //      }
+      //    }
+      //  });
+      //}
+      //else {
+      //  DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().removeBreakpoint(this);
+      //}
     }
   }
 
@@ -422,11 +425,10 @@
   }
 
   public boolean isAt(@NotNull Document document, int offset) {
-    RangeHighlighter highlighter = getHighlighter();
-    return highlighter != null &&
-           highlighter.isValid() &&
-           document.equals(highlighter.getDocument()) &&
-           getSourcePosition().getLine() == document.getLineNumber(offset);
+    final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
+    int line = document.getLineNumber(offset);
+    XSourcePosition position = myXBreakpoint.getSourcePosition();
+    return position != null && position.getLine() == line && position.getFile().equals(file);
   }
 
   protected void reload(PsiFile psiFile) {
@@ -448,9 +450,9 @@
     });
   }
 
-  private void setupGutterRenderer(@NotNull RangeHighlighter highlighter) {
-    highlighter.setGutterIconRenderer(new MyGutterIconRenderer(getIcon(), getDescription()));
-  }
+  //private void setupGutterRenderer(@NotNull RangeHighlighter highlighter) {
+  //  highlighter.setGutterIconRenderer(new MyGutterIconRenderer(getIcon(), getDescription()));
+  //}
 
   @Override
   public abstract Key<? extends BreakpointWithHighlighter> getCategory();
@@ -559,7 +561,7 @@
   public void readExternal(@NotNull Element breakpointNode) throws InvalidDataException {
     super.readExternal(breakpointNode);
     //noinspection HardCodedStringLiteral
-    final String url = breakpointNode.getAttributeValue("url");
+    //final String url = breakpointNode.getAttributeValue("url");
 
     //noinspection HardCodedStringLiteral
     final String className = breakpointNode.getAttributeValue("class");
@@ -573,146 +575,146 @@
       myPackageName = packageName;
     }
 
-    VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
-    if (vFile == null) {
-      throw new InvalidDataException(DebuggerBundle.message("error.breakpoint.file.not.found", url));
-    }
-    final Document doc = FileDocumentManager.getInstance().getDocument(vFile);
-    if (doc == null) {
-      throw new InvalidDataException(DebuggerBundle.message("error.cannot.load.breakpoint.file", url));
-    }
-
-    // line number
-    final int line;
-    try {
-      //noinspection HardCodedStringLiteral
-      line = Integer.parseInt(breakpointNode.getAttributeValue("line"));
-    }
-    catch (Exception e) {
-      throw new InvalidDataException("Line number is invalid for breakpoint");
-    }
-    if (line < 0) {
-      throw new InvalidDataException("Line number is invalid for breakpoint");
-    }
-
-    RangeHighlighter highlighter = createHighlighter(myProject, doc, line);
-
-    if (highlighter == null) {
-      throw new InvalidDataException("");
-    }
-
-    myHighlighter = highlighter;
-    reload();
+    //VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
+    //if (vFile == null) {
+    //  throw new InvalidDataException(DebuggerBundle.message("error.breakpoint.file.not.found", url));
+    //}
+    //final Document doc = FileDocumentManager.getInstance().getDocument(vFile);
+    //if (doc == null) {
+    //  throw new InvalidDataException(DebuggerBundle.message("error.cannot.load.breakpoint.file", url));
+    //}
+    //
+    //// line number
+    //final int line;
+    //try {
+    //  //noinspection HardCodedStringLiteral
+    //  line = Integer.parseInt(breakpointNode.getAttributeValue("line"));
+    //}
+    //catch (Exception e) {
+    //  throw new InvalidDataException("Line number is invalid for breakpoint");
+    //}
+    //if (line < 0) {
+    //  throw new InvalidDataException("Line number is invalid for breakpoint");
+    //}
+    //
+    //RangeHighlighter highlighter = createHighlighter(myProject, doc, line);
+    //
+    //if (highlighter == null) {
+    //  throw new InvalidDataException("");
+    //}
+    //
+    //myHighlighter = highlighter;
+    //reload();
   }
+  //
+  //@Override
+  //@SuppressWarnings({"HardCodedStringLiteral"})
+  //public void writeExternal(@NotNull Element parentNode) throws WriteExternalException {
+  //  super.writeExternal(parentNode);
+  //  PsiFile psiFile = getSourcePosition().getFile();
+  //  final VirtualFile virtualFile = psiFile.getVirtualFile();
+  //  final String url = virtualFile != null ? virtualFile.getUrl() : "";
+  //  parentNode.setAttribute("url", url);
+  //  parentNode.setAttribute("line", Integer.toString(getSourcePosition().getLine()));
+  //  if (myClassName != null) {
+  //    parentNode.setAttribute("class", myClassName);
+  //  }
+  //  if (myPackageName != null) {
+  //    parentNode.setAttribute("package", myPackageName);
+  //  }
+  //}
 
-  @Override
-  @SuppressWarnings({"HardCodedStringLiteral"})
-  public void writeExternal(@NotNull Element parentNode) throws WriteExternalException {
-    super.writeExternal(parentNode);
-    PsiFile psiFile = getSourcePosition().getFile();
-    final VirtualFile virtualFile = psiFile.getVirtualFile();
-    final String url = virtualFile != null ? virtualFile.getUrl() : "";
-    parentNode.setAttribute("url", url);
-    parentNode.setAttribute("line", Integer.toString(getSourcePosition().getLine()));
-    if (myClassName != null) {
-      parentNode.setAttribute("class", myClassName);
-    }
-    if (myPackageName != null) {
-      parentNode.setAttribute("package", myPackageName);
-    }
-  }
-
-  private class MyGutterIconRenderer extends GutterIconRenderer {
-    private final Icon myIcon;
-    private final String myDescription;
-
-    public MyGutterIconRenderer(@NotNull Icon icon, @NotNull String description) {
-      myIcon = icon;
-      myDescription = description;
-    }
-
-    @Override
-    @NotNull
-    public Icon getIcon() {
-      return myIcon;
-    }
-
-    @Override
-    public String getTooltipText() {
-      return myDescription;
-    }
-
-    @Override
-    public Alignment getAlignment() {
-      return Alignment.RIGHT;
-    }
-
-    @Override
-    public AnAction getClickAction() {
-      return new AnAction() {
-        @Override
-        public void actionPerformed(AnActionEvent e) {
-          DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().removeBreakpoint(BreakpointWithHighlighter.this);
-        }
-      };
-    }
-
-    @Override
-    public AnAction getMiddleButtonClickAction() {
-      return new AnAction() {
-        @Override
-        public void actionPerformed(AnActionEvent e) {
-          ENABLED = !ENABLED;
-          DebuggerManagerEx.getInstanceEx(getProject()).getBreakpointManager().fireBreakpointChanged(BreakpointWithHighlighter.this);
-          updateUI();
-        }
-      };
-    }
-
-    @Override
-    public ActionGroup getPopupMenuActions() {
-      return null;
-    }
-
-    @Nullable
-    @Override
-    public AnAction getRightButtonClickAction() {
-      return new EditBreakpointAction.ContextAction(this, BreakpointWithHighlighter.this, DebuggerSupport.getDebuggerSupport(JavaDebuggerSupport.class));
-    }
-
-    @Override
-    public GutterDraggableObject getDraggableObject() {
-      return new GutterDraggableObject() {
-        @Override
-        public boolean copy(int line, @NotNull VirtualFile file) {
-          final PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(file);
-          return psiFile != null && moveTo(SourcePosition.createFromLine(psiFile, line));
-        }
-
-        @Override
-        public Cursor getCursor(int line) {
-          final SourcePosition newPosition = SourcePosition.createFromLine(getSourcePosition().getFile(), line);
-          return canMoveTo(newPosition) ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop;
-        }
-      };
-    }
-
-    @Override
-    public boolean equals(@NotNull Object obj) {
-      return obj instanceof MyGutterIconRenderer &&
-             Comparing.equal(getTooltipText(), ((MyGutterIconRenderer)obj).getTooltipText()) &&
-             Comparing.equal(getIcon(), ((MyGutterIconRenderer)obj).getIcon());
-    }
-
-    @Override
-    public int hashCode() {
-      return getIcon().hashCode();
-    }
-
-    @Override
-    public String toString() {
-      return "LB " + getDisplayName();
-    }
-  }
+  //private class MyGutterIconRenderer extends GutterIconRenderer {
+  //  private final Icon myIcon;
+  //  private final String myDescription;
+  //
+  //  public MyGutterIconRenderer(@NotNull Icon icon, @NotNull String description) {
+  //    myIcon = icon;
+  //    myDescription = description;
+  //  }
+  //
+  //  @Override
+  //  @NotNull
+  //  public Icon getIcon() {
+  //    return myIcon;
+  //  }
+  //
+  //  @Override
+  //  public String getTooltipText() {
+  //    return myDescription;
+  //  }
+  //
+  //  @Override
+  //  public Alignment getAlignment() {
+  //    return Alignment.RIGHT;
+  //  }
+  //
+  //  @Override
+  //  public AnAction getClickAction() {
+  //    return new AnAction() {
+  //      @Override
+  //      public void actionPerformed(AnActionEvent e) {
+  //        DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().removeBreakpoint(BreakpointWithHighlighter.this);
+  //      }
+  //    };
+  //  }
+  //
+  //  @Override
+  //  public AnAction getMiddleButtonClickAction() {
+  //    return new AnAction() {
+  //      @Override
+  //      public void actionPerformed(AnActionEvent e) {
+  //        setEnabled(!isEnabled());
+  //        DebuggerManagerEx.getInstanceEx(getProject()).getBreakpointManager().fireBreakpointChanged(BreakpointWithHighlighter.this);
+  //        updateUI();
+  //      }
+  //    };
+  //  }
+  //
+  //  @Override
+  //  public ActionGroup getPopupMenuActions() {
+  //    return null;
+  //  }
+  //
+  //  @Nullable
+  //  @Override
+  //  public AnAction getRightButtonClickAction() {
+  //    return new EditBreakpointAction.ContextAction(this, BreakpointWithHighlighter.this, DebuggerSupport.getDebuggerSupport(JavaDebuggerSupport.class));
+  //  }
+  //
+  //  @Override
+  //  public GutterDraggableObject getDraggableObject() {
+  //    return new GutterDraggableObject() {
+  //      @Override
+  //      public boolean copy(int line, @NotNull VirtualFile file) {
+  //        final PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(file);
+  //        return psiFile != null && moveTo(SourcePosition.createFromLine(psiFile, line));
+  //      }
+  //
+  //      @Override
+  //      public Cursor getCursor(int line) {
+  //        final SourcePosition newPosition = SourcePosition.createFromLine(getSourcePosition().getFile(), line);
+  //        return canMoveTo(newPosition) ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop;
+  //      }
+  //    };
+  //  }
+  //
+  //  @Override
+  //  public boolean equals(@NotNull Object obj) {
+  //    return obj instanceof MyGutterIconRenderer &&
+  //           Comparing.equal(getTooltipText(), ((MyGutterIconRenderer)obj).getTooltipText()) &&
+  //           Comparing.equal(getIcon(), ((MyGutterIconRenderer)obj).getIcon());
+  //  }
+  //
+  //  @Override
+  //  public int hashCode() {
+  //    return getIcon().hashCode();
+  //  }
+  //
+  //  @Override
+  //  public String toString() {
+  //    return "LB " + getDisplayName();
+  //  }
+  //}
 
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java
index c6a1955..8a0b515 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java
@@ -34,13 +34,14 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.JDOMExternalizerUtil;
 import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.WriteExternalException;
 import com.intellij.psi.JavaPsiFacade;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.sun.jdi.AbsentInformationException;
 import com.sun.jdi.Location;
 import com.sun.jdi.ObjectReference;
@@ -50,36 +51,32 @@
 import com.sun.jdi.request.ExceptionRequest;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaExceptionBreakpointProperties;
 
 import javax.swing.*;
 
-public class ExceptionBreakpoint extends Breakpoint {
+public class ExceptionBreakpoint extends Breakpoint<JavaExceptionBreakpointProperties> {
   private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.breakpoints.ExceptionBreakpoint");
 
-  public boolean NOTIFY_CAUGHT   = true;
-  public boolean NOTIFY_UNCAUGHT = true;
-  private String myQualifiedName;
-  private String myPackageName;
-
   protected final static String READ_NO_CLASS_NAME = DebuggerBundle.message("error.absent.exception.breakpoint.class.name");
   public static final @NonNls Key<ExceptionBreakpoint> CATEGORY = BreakpointCategory.lookup("exception_breakpoints");
 
-  public ExceptionBreakpoint(Project project) {
-    super(project);
+  public ExceptionBreakpoint(Project project, XBreakpoint xBreakpoint) {
+    super(project, xBreakpoint);
   }
 
   public Key<? extends ExceptionBreakpoint> getCategory() {
     return CATEGORY;
   }
 
-  protected ExceptionBreakpoint(Project project, String qualifiedName, String packageName) {
-    super(project);
-    myQualifiedName = qualifiedName;
+  protected ExceptionBreakpoint(Project project, String qualifiedName, String packageName, XBreakpoint xBreakpoint) {
+    super(project, xBreakpoint);
+    setQualifiedName(qualifiedName);
     if (packageName == null) {
-      myPackageName = calcPackageName(qualifiedName);
+      setPackageName(calcPackageName(qualifiedName));
     }
     else {
-      myPackageName = packageName;
+      setPackageName(packageName);
     }
   }
 
@@ -92,27 +89,27 @@
   }
 
   public String getClassName() {
-    return myQualifiedName;
+    return getQualifiedName();
   }
 
   public String getPackageName() {
-    return myPackageName;
+    return getProperties().myPackageName;
   }
 
   public PsiClass getPsiClass() {
     return PsiDocumentManager.getInstance(myProject).commitAndRunReadAction(new Computable<PsiClass>() {
       public PsiClass compute() {
-        return myQualifiedName != null ? DebuggerUtilsEx.findClass(myQualifiedName, myProject, GlobalSearchScope.allScope(myProject)) : null;
+        return getQualifiedName() != null ? DebuggerUtilsEx.findClass(getQualifiedName(), myProject, GlobalSearchScope.allScope(myProject)) : null;
       }
     });
   }
 
   public String getDisplayName() {
-    return DebuggerBundle.message("breakpoint.exception.breakpoint.display.name", myQualifiedName);
+    return DebuggerBundle.message("breakpoint.exception.breakpoint.display.name", getQualifiedName());
   }
 
   public Icon getIcon() {
-    if (!ENABLED) {
+    if (!isEnabled()) {
       final Breakpoint master = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().findMasterBreakpoint(this);
       return master == null? AllIcons.Debugger.Db_disabled_exception_breakpoint : AllIcons.Debugger.Db_dep_exception_breakpoint;
     }
@@ -124,20 +121,20 @@
 
   public void createRequest(final DebugProcessImpl debugProcess) {
     DebuggerManagerThreadImpl.assertIsManagerThread();
-    if (!ENABLED || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+    if (!isEnabled() || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
       return;
     }
 
     SourcePosition classPosition = PsiDocumentManager.getInstance(myProject).commitAndRunReadAction(new Computable<SourcePosition>() {
       public SourcePosition compute() {
-        PsiClass psiClass = DebuggerUtilsEx.findClass(myQualifiedName, myProject, debugProcess.getSearchScope());
+        PsiClass psiClass = DebuggerUtilsEx.findClass(getQualifiedName(), myProject, debugProcess.getSearchScope());
 
         return psiClass != null ? SourcePosition.createFromElement(psiClass) : null;
       }
     });
 
     if(classPosition == null) {
-      createOrWaitPrepare(debugProcess, myQualifiedName);
+      createOrWaitPrepare(debugProcess, getQualifiedName());
     }
     else {
       createOrWaitPrepare(debugProcess, classPosition);
@@ -146,11 +143,12 @@
 
   public void processClassPrepare(DebugProcess process, ReferenceType refType) {
     DebugProcessImpl debugProcess = (DebugProcessImpl)process;
-    if (!ENABLED) {
+    if (!isEnabled()) {
       return;
     }
     // trying to create a request
-    ExceptionRequest request = debugProcess.getRequestsManager().createExceptionRequest(this, refType, NOTIFY_CAUGHT, NOTIFY_UNCAUGHT);
+    ExceptionRequest request = debugProcess.getRequestsManager().createExceptionRequest(this, refType, isNotifyCaught(),
+                                                                                        isNotifyUncaught());
     debugProcess.getRequestsManager().enableRequest(request);
     if (LOG.isDebugEnabled()) {
       if (refType != null) {
@@ -170,7 +168,7 @@
   }
 
   public String getEventMessage(LocatableEvent event) {
-    String exceptionName = (myQualifiedName != null)? myQualifiedName : "java.lang.Throwable";
+    String exceptionName = (getQualifiedName() != null)? getQualifiedName() : "java.lang.Throwable";
     String threadName    = null;
     if (event instanceof ExceptionEvent) {
       ExceptionEvent exceptionEvent = (ExceptionEvent)event;
@@ -216,15 +214,15 @@
     return true;
   }
 
-  @SuppressWarnings({"HardCodedStringLiteral"}) public void writeExternal(Element parentNode) throws WriteExternalException {
-    super.writeExternal(parentNode);
-    if(myQualifiedName != null) {
-      parentNode.setAttribute("class_name", myQualifiedName);
-    }
-    if(myPackageName != null) {
-      parentNode.setAttribute("package_name", myPackageName);
-    }
-  }
+  //@SuppressWarnings({"HardCodedStringLiteral"}) public void writeExternal(Element parentNode) throws WriteExternalException {
+  //  super.writeExternal(parentNode);
+  //  if(getQualifiedName() != null) {
+  //    parentNode.setAttribute("class_name", getQualifiedName());
+  //  }
+  //  if(getPackageName() != null) {
+  //    parentNode.setAttribute("package_name", getPackageName());
+  //  }
+  //}
 
   public PsiElement getEvaluationElement() {
     if (getClassName() == null) {
@@ -235,16 +233,45 @@
 
   public void readExternal(Element parentNode) throws InvalidDataException {
     super.readExternal(parentNode);
-    //noinspection HardCodedStringLiteral
-    String className = parentNode.getAttributeValue("class_name");
-    myQualifiedName = className;
-    if(className == null) {
-      throw new InvalidDataException(READ_NO_CLASS_NAME);
-    }
 
     //noinspection HardCodedStringLiteral
     String packageName = parentNode.getAttributeValue("package_name");
-    myPackageName = packageName != null? packageName : calcPackageName(packageName);
+    setPackageName(packageName != null? packageName : calcPackageName(packageName));
+
+    try {
+      getProperties().NOTIFY_CAUGHT = Boolean.valueOf(JDOMExternalizerUtil.readField(parentNode, "NOTIFY_CAUGHT"));
+    } catch (Exception e) {
+    }
+    try {
+      getProperties().NOTIFY_UNCAUGHT = Boolean.valueOf(JDOMExternalizerUtil.readField(parentNode, "NOTIFY_UNCAUGHT"));
+    } catch (Exception e) {
+    }
+
+    //noinspection HardCodedStringLiteral
+    String className = parentNode.getAttributeValue("class_name");
+    setQualifiedName(className);
+    if(className == null) {
+      throw new InvalidDataException(READ_NO_CLASS_NAME);
+    }
   }
 
+  private boolean isNotifyCaught() {
+    return getProperties().NOTIFY_CAUGHT;
+  }
+
+  private boolean isNotifyUncaught() {
+    return getProperties().NOTIFY_UNCAUGHT;
+  }
+
+  private String getQualifiedName() {
+    return getProperties().myQualifiedName;
+  }
+
+  private void setQualifiedName(String qualifiedName) {
+    getProperties().myQualifiedName = qualifiedName;
+  }
+
+  private void setPackageName(String packageName) {
+    getProperties().myPackageName = packageName;
+  }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java
deleted file mode 100644
index 40b75c4..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.ui.breakpoints;
-
-import com.intellij.debugger.DebuggerBundle;
-import com.intellij.debugger.DebuggerManagerEx;
-import com.intellij.debugger.HelpID;
-import com.intellij.debugger.engine.JVMNameUtil;
-import com.intellij.icons.AllIcons;
-import com.intellij.ide.util.TreeClassChooser;
-import com.intellij.ide.util.TreeClassChooserFactory;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import com.intellij.psi.JavaPsiFacade;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiClassOwner;
-import com.intellij.psi.search.GlobalSearchScope;
-import org.jdom.Element;
-
-import javax.swing.*;
-
-/**
- * @author Eugene Zhuravlev
- *         Date: Apr 26, 2005
- */
-public class ExceptionBreakpointFactory extends BreakpointFactory {
-  public Breakpoint createBreakpoint(Project project, final Element element) {
-    return new ExceptionBreakpoint(project);
-  }
-
-  public Icon getIcon() {
-    return AllIcons.Debugger.Db_exception_breakpoint;
-  }
-
-  public Icon getDisabledIcon() {
-    return AllIcons.Debugger.Db_disabled_exception_breakpoint;
-  }
-
-  @Override
-  protected String getHelpID() {
-    return HelpID.EXCEPTION_BREAKPOINTS;
-  }
-
-  @Override
-  public String getDisplayName() {
-    return DebuggerBundle.message("exception.breakpoints.tab.title");
-  }
-
-  @Override
-  public BreakpointPropertiesPanel createBreakpointPropertiesPanel(Project project, boolean compact) {
-    return new ExceptionBreakpointPropertiesPanel(project, compact);
-  }
-
-  public Key<ExceptionBreakpoint> getBreakpointCategory() {
-    return ExceptionBreakpoint.CATEGORY;
-  }
-
-  @Override
-  public boolean canAddBreakpoints() {
-    return true;
-  }
-
-  @Override
-  public Breakpoint addBreakpoint(Project project) {
-    ExceptionBreakpoint breakpoint = null;
-    final PsiClass throwableClass =
-      JavaPsiFacade.getInstance(project).findClass("java.lang.Throwable", GlobalSearchScope.allScope(project));
-    TreeClassChooser chooser = TreeClassChooserFactory.getInstance(project)
-      .createInheritanceClassChooser(DebuggerBundle.message("add.exception.breakpoint.classchooser.title"),
-                                     GlobalSearchScope.allScope(project), throwableClass, true, true, null);
-    chooser.showDialog();
-    PsiClass selectedClass = chooser.getSelected();
-    String qName = selectedClass == null ? null : JVMNameUtil.getNonAnonymousClassName(selectedClass);
-
-    if (qName != null && qName.length() > 0) {
-      breakpoint = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager()
-        .addExceptionBreakpoint(qName, ((PsiClassOwner)selectedClass.getContainingFile()).getPackageName());
-    }
-    return breakpoint;
-  }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointPropertiesPanel.java
index 6d02499..4af7275 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointPropertiesPanel.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointPropertiesPanel.java
@@ -21,31 +21,34 @@
 package com.intellij.debugger.ui.breakpoints;
 
 import com.intellij.debugger.DebuggerBundle;
-import com.intellij.ide.util.ClassFilter;
-import com.intellij.openapi.project.Project;
 import com.intellij.ui.IdeBorderFactory;
 import com.intellij.util.ui.DialogUtil;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaExceptionBreakpointProperties;
 
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 
-public class ExceptionBreakpointPropertiesPanel extends BreakpointPropertiesPanel {
+public class ExceptionBreakpointPropertiesPanel extends XBreakpointCustomPropertiesPanel<XBreakpoint<JavaExceptionBreakpointProperties>> {
   private JCheckBox myNotifyCaughtCheckBox;
   private JCheckBox myNotifyUncaughtCheckBox;
-  private ExceptionBreakpoint myExceptionBreakpoint;
+  //private ExceptionBreakpoint myExceptionBreakpoint;
 
-  public ExceptionBreakpointPropertiesPanel(Project project, boolean compact) {
-    super(project, ExceptionBreakpoint.CATEGORY, compact);
-  }
+  //public ExceptionBreakpointPropertiesPanel(Project project, boolean compact) {
+  //  super(project, ExceptionBreakpoint.CATEGORY, compact);
+  //}
 
-  protected ClassFilter createClassConditionFilter() {
-    return null;
-  }
+  //protected ClassFilter createClassConditionFilter() {
+  //  return null;
+  //}
 
-  protected JComponent createSpecialBox() {
-
+  @NotNull
+  @Override
+  public JComponent getComponent() {
     myNotifyCaughtCheckBox = new JCheckBox(DebuggerBundle.message("label.exception.breakpoint.properties.panel.caught.exception"));
     myNotifyUncaughtCheckBox = new JCheckBox(DebuggerBundle.message("label.exception.breakpoint.properties.panel.uncaught.exception"));
     DialogUtil.registerMnemonic(myNotifyCaughtCheckBox);
@@ -91,25 +94,20 @@
     return _panel;
   }
 
-  protected void updateCheckboxes() {
-    super.updateCheckboxes();
-    myPassCountCheckbox.setEnabled(!(myExceptionBreakpoint instanceof AnyExceptionBreakpoint));
+  //protected void updateCheckboxes() {
+  //  super.updateCheckboxes();
+  //  myPassCountCheckbox.setEnabled(!(myExceptionBreakpoint instanceof AnyExceptionBreakpoint));
+  //}
+
+  @Override
+  public void loadFrom(@NotNull XBreakpoint<JavaExceptionBreakpointProperties> breakpoint) {
+    myNotifyCaughtCheckBox.setSelected(breakpoint.getProperties().NOTIFY_CAUGHT);
+    myNotifyUncaughtCheckBox.setSelected(breakpoint.getProperties().NOTIFY_UNCAUGHT);
   }
 
-  public void initFrom(Breakpoint breakpoint, boolean moreOptionsVisible) {
-    ExceptionBreakpoint exceptionBreakpoint = (ExceptionBreakpoint)breakpoint;
-    myExceptionBreakpoint = exceptionBreakpoint;
-    super.initFrom(breakpoint, moreOptionsVisible);
-
-    myNotifyCaughtCheckBox.setSelected(exceptionBreakpoint.NOTIFY_CAUGHT);
-    myNotifyUncaughtCheckBox.setSelected(exceptionBreakpoint.NOTIFY_UNCAUGHT);
-  }
-
-  public void saveTo(Breakpoint breakpoint) {
-    ExceptionBreakpoint exceptionBreakpoint = (ExceptionBreakpoint)breakpoint;
-    exceptionBreakpoint.NOTIFY_CAUGHT = myNotifyCaughtCheckBox.isSelected();
-    exceptionBreakpoint.NOTIFY_UNCAUGHT = myNotifyUncaughtCheckBox.isSelected();
-
-    super.saveTo(breakpoint);
+  @Override
+  public void saveTo(@NotNull XBreakpoint<JavaExceptionBreakpointProperties> breakpoint) {
+    breakpoint.getProperties().NOTIFY_CAUGHT = myNotifyCaughtCheckBox.isSelected();
+    breakpoint.getProperties().NOTIFY_UNCAUGHT = myNotifyUncaughtCheckBox.isSelected();
   }
 }
\ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpoint.java
index 365ae24..aa3a295 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpoint.java
@@ -33,19 +33,17 @@
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.JDOMExternalizerUtil;
 import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.Processor;
 import com.intellij.util.text.CharArrayUtil;
 import com.intellij.xdebugger.XDebuggerUtil;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.sun.jdi.*;
 import com.sun.jdi.event.AccessWatchpointEvent;
 import com.sun.jdi.event.LocatableEvent;
@@ -55,26 +53,23 @@
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaFieldBreakpointProperties;
 
 import javax.swing.*;
-import java.util.List;
 
-public class FieldBreakpoint extends BreakpointWithHighlighter {
+public class FieldBreakpoint extends BreakpointWithHighlighter<JavaFieldBreakpointProperties> {
   private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.breakpoints.FieldBreakpoint");
-  public boolean WATCH_MODIFICATION = true;
-  public boolean WATCH_ACCESS       = false;
   private boolean myIsStatic;
-  private String myFieldName;
 
   @NonNls public static final Key<FieldBreakpoint> CATEGORY = BreakpointCategory.lookup("field_breakpoints");
 
-  protected FieldBreakpoint(Project project) {
-    super(project);
+  protected FieldBreakpoint(Project project, XBreakpoint breakpoint) {
+    super(project, breakpoint);
   }
 
-  private FieldBreakpoint(Project project, RangeHighlighter highlighter, @NotNull String fieldName) {
-    super(project, highlighter);
-    myFieldName = fieldName;
+  private FieldBreakpoint(Project project, @NotNull String fieldName, XBreakpoint breakpoint) {
+    super(project, breakpoint);
+    setFieldName(fieldName);
   }
 
   public boolean isStatic() {
@@ -82,10 +77,9 @@
   }
 
   public String getFieldName() {
-    return myFieldName;
+    return getProperties().myFieldName;
   }
 
-
   @Override
   protected Icon getDisabledIcon(boolean isMuted) {
     final Breakpoint master = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().findMasterBreakpoint(this);
@@ -128,7 +122,7 @@
       @Override
       public PsiField compute() {
         final PsiClass psiClass = getPsiClassAt(sourcePosition);
-        return psiClass != null ? psiClass.findFieldByName(myFieldName, true) : null;
+        return psiClass != null ? psiClass.findFieldByName(getFieldName(), true) : null;
       }
     });
     if (field != null) {
@@ -142,11 +136,15 @@
     super.reload(psiFile);
     PsiField field = PositionUtil.getPsiElementAt(getProject(), PsiField.class, getSourcePosition());
     if(field != null) {
-      myFieldName = field.getName();
+      setFieldName(field.getName());
+      PsiClass psiClass = field.getContainingClass();
+      if (psiClass != null) {
+        getProperties().myClassName = psiClass.getQualifiedName();
+      }
       myIsStatic = field.hasModifierProperty(PsiModifier.STATIC);
     }
     if (myIsStatic) {
-      INSTANCE_FILTERS_ENABLED = false;
+      setInstanceFiltersEnabled(false);
     }
   }
 
@@ -181,20 +179,21 @@
                                             ReferenceType refType) {
     VirtualMachineProxy vm = debugProcess.getVirtualMachineProxy();
     try {
-      Field field = refType.fieldByName(myFieldName);
+      Field field = refType.fieldByName(getFieldName());
       if (field == null) {
-        debugProcess.getRequestsManager().setInvalid(this, DebuggerBundle.message("error.invalid.breakpoint.missing.field.in.class", myFieldName, refType.name()));
+        debugProcess.getRequestsManager().setInvalid(this, DebuggerBundle.message("error.invalid.breakpoint.missing.field.in.class",
+                                                                                  getFieldName(), refType.name()));
         return;
       }
       RequestManagerImpl manager = debugProcess.getRequestsManager();
-      if (WATCH_MODIFICATION && vm.canWatchFieldModification()) {
+      if (isWatchModification() && vm.canWatchFieldModification()) {
         ModificationWatchpointRequest request = manager.createModificationWatchpointRequest(this, field);
         debugProcess.getRequestsManager().enableRequest(request);
         if (LOG.isDebugEnabled()) {
           LOG.debug("Modification request added");
         }
       }
-      if (WATCH_ACCESS && vm.canWatchFieldAccess()) {
+      if (isWatchAccess() && vm.canWatchFieldAccess()) {
         AccessWatchpointRequest request = manager.createAccessWatchpointRequest(this, field);
         debugProcess.getRequestsManager().enableRequest(request);
         if (LOG.isDebugEnabled()) {
@@ -284,11 +283,11 @@
       return DebuggerBundle.message("status.breakpoint.invalid");
     }
     final String className = getClassName();
-    return className != null && !className.isEmpty() ? className + "." + myFieldName : myFieldName;
+    return className != null && !className.isEmpty() ? className + "." + getFieldName() : getFieldName();
   }
 
-  public static FieldBreakpoint create(@NotNull Project project, @NotNull Document document, int lineIndex, String fieldName) {
-    FieldBreakpoint breakpoint = new FieldBreakpoint(project, createHighlighter(project, document, lineIndex), fieldName);
+  public static FieldBreakpoint create(@NotNull Project project, String fieldName, XBreakpoint xBreakpoint) {
+    FieldBreakpoint breakpoint = new FieldBreakpoint(project, fieldName, xBreakpoint);
     return (FieldBreakpoint)breakpoint.init();
   }
 
@@ -308,39 +307,39 @@
     return field == getPsiField();
   }
 
-  protected static FieldBreakpoint create(@NotNull Project project, @NotNull Field field, ObjectReference object) {
-    String fieldName = field.name();
-    int line = 0;
-    Document document = null;
-    try {
-      List locations = field.declaringType().allLineLocations();
-      if(!locations.isEmpty()) {
-        Location location = (Location)locations.get(0);
-        line = location.lineNumber();
-        VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(location.sourcePath());
-        if(file != null) {
-          PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
-          if(psiFile != null) {
-            document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
-          }
-        }
-      }
-    }
-    catch (AbsentInformationException e) {
-      LOG.debug(e);
-    }
-    catch (InternalError e) {
-      LOG.debug(e);
-    }
-
-    if(document == null) return null;
-
-    FieldBreakpoint fieldBreakpoint = new FieldBreakpoint(project, createHighlighter(project, document, line), fieldName);
-    if (!fieldBreakpoint.isStatic()) {
-      fieldBreakpoint.addInstanceFilter(object.uniqueID());
-    }
-    return (FieldBreakpoint)fieldBreakpoint.init();
-  }
+  //protected static FieldBreakpoint create(@NotNull Project project, @NotNull Field field, ObjectReference object, XBreakpoint xBreakpoint) {
+  //  String fieldName = field.name();
+  //  int line = 0;
+  //  Document document = null;
+  //  try {
+  //    List locations = field.declaringType().allLineLocations();
+  //    if(!locations.isEmpty()) {
+  //      Location location = (Location)locations.get(0);
+  //      line = location.lineNumber();
+  //      VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(location.sourcePath());
+  //      if(file != null) {
+  //        PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
+  //        if(psiFile != null) {
+  //          document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
+  //        }
+  //      }
+  //    }
+  //  }
+  //  catch (AbsentInformationException e) {
+  //    LOG.debug(e);
+  //  }
+  //  catch (InternalError e) {
+  //    LOG.debug(e);
+  //  }
+  //
+  //  if(document == null) return null;
+  //
+  //  FieldBreakpoint fieldBreakpoint = new FieldBreakpoint(project, createHighlighter(project, document, line), fieldName, xBreakpoint);
+  //  if (!fieldBreakpoint.isStatic()) {
+  //    fieldBreakpoint.addInstanceFilter(object.uniqueID());
+  //  }
+  //  return (FieldBreakpoint)fieldBreakpoint.init();
+  //}
 
   public static PsiField findField(Project project, Document document, int offset) {
     PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
@@ -373,21 +372,41 @@
   public void readExternal(@NotNull Element breakpointNode) throws InvalidDataException {
     super.readExternal(breakpointNode);
     //noinspection HardCodedStringLiteral
-    myFieldName = breakpointNode.getAttributeValue("field_name");
-    if(myFieldName == null) {
+    setFieldName(breakpointNode.getAttributeValue("field_name"));
+    if(getFieldName() == null) {
       throw new InvalidDataException("No field name for field breakpoint");
     }
+    try {
+      getProperties().WATCH_MODIFICATION = Boolean.valueOf(JDOMExternalizerUtil.readField(breakpointNode, "WATCH_MODIFICATION"));
+    } catch (Exception e) {
+    }
+    try {
+      getProperties().WATCH_ACCESS = Boolean.valueOf(JDOMExternalizerUtil.readField(breakpointNode, "WATCH_ACCESS"));
+    } catch (Exception e) {
+    }
   }
-
-  @Override
-  @SuppressWarnings({"HardCodedStringLiteral"})
-  public void writeExternal(@NotNull Element parentNode) throws WriteExternalException {
-    super.writeExternal(parentNode);
-    parentNode.setAttribute("field_name", getFieldName());
-  }
+  //
+  //@Override
+  //@SuppressWarnings({"HardCodedStringLiteral"})
+  //public void writeExternal(@NotNull Element parentNode) throws WriteExternalException {
+  //  super.writeExternal(parentNode);
+  //  parentNode.setAttribute("field_name", getFieldName());
+  //}
 
   @Override
   public PsiElement getEvaluationElement() {
     return getPsiClass();
   }
+
+  private boolean isWatchModification() {
+    return getProperties().WATCH_MODIFICATION;
+  }
+
+  private boolean isWatchAccess() {
+    return getProperties().WATCH_ACCESS;
+  }
+
+  private void setFieldName(String fieldName) {
+    getProperties().myFieldName = fieldName;
+  }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java
deleted file mode 100644
index 1bdef0c..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.ui.breakpoints;
-
-import com.intellij.CommonBundle;
-import com.intellij.debugger.DebuggerBundle;
-import com.intellij.debugger.DebuggerManagerEx;
-import com.intellij.debugger.HelpID;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Ref;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import org.jdom.Element;
-
-import javax.swing.*;
-
-/**
- * @author Eugene Zhuravlev
- *         Date: Apr 26, 2005
- */
-public class FieldBreakpointFactory extends BreakpointFactory{
-  public Breakpoint createBreakpoint(Project project, final Element element) {
-    return new FieldBreakpoint(project);
-  }
-
-  public Icon getIcon() {
-    return AllIcons.Debugger.Db_field_breakpoint;
-  }
-
-  public Icon getDisabledIcon() {
-    return AllIcons.Debugger.Db_disabled_field_breakpoint;
-  }
-
-  @Override
-  protected String getHelpID() {
-    return HelpID.FIELD_WATCHPOINTS;
-  }
-
-  @Override
-  public String getDisplayName() {
-    return DebuggerBundle.message("field.watchpoints.tab.title");
-  }
-
-  @Override
-  public BreakpointPropertiesPanel createBreakpointPropertiesPanel(Project project, boolean compact) {
-    return new FieldBreakpointPropertiesPanel(project, compact);
-  }
-
-  public Key<FieldBreakpoint> getBreakpointCategory() {
-    return FieldBreakpoint.CATEGORY;
-  }
-
-  @Override
-  public Breakpoint addBreakpoint(final Project project) {
-    final Ref<Breakpoint> result = Ref.create(null);
-    AddFieldBreakpointDialog dialog = new AddFieldBreakpointDialog(project) {
-      protected boolean validateData() {
-        String className = getClassName();
-        if (className.length() == 0) {
-          Messages.showMessageDialog(project, DebuggerBundle.message("error.field.breakpoint.class.name.not.specified"),
-                                     DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon());
-          return false;
-        }
-        String fieldName = getFieldName();
-        if (fieldName.length() == 0) {
-          Messages.showMessageDialog(project, DebuggerBundle.message("error.field.breakpoint.field.name.not.specified"),
-                                     DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon());
-          return false;
-        }
-        PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(className, GlobalSearchScope.allScope(project));
-        if (psiClass != null) {
-          PsiFile psiFile  = psiClass.getContainingFile();
-          Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
-          if(document != null) {
-            PsiField field = psiClass.findFieldByName(fieldName, true);
-            if(field != null) {
-              int line = document.getLineNumber(field.getTextOffset());
-              FieldBreakpoint fieldBreakpoint = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().addFieldBreakpoint(document, line, fieldName);
-              if (fieldBreakpoint != null) {
-                result.set(fieldBreakpoint);
-                return true;
-              }
-            }
-            else {
-              Messages.showMessageDialog(project,
-                DebuggerBundle.message("error.field.breakpoint.field.not.found", className, fieldName, fieldName),
-                CommonBundle.getErrorTitle(),
-                Messages.getErrorIcon()
-              );
-            }
-          }
-        } else {
-          Messages.showMessageDialog(project,
-            DebuggerBundle.message("error.field.breakpoint.class.sources.not.found", className, fieldName, className),
-            CommonBundle.getErrorTitle(),
-            Messages.getErrorIcon()
-          );
-        }
-        return false;
-      }
-    };
-    dialog.show();
-    return result.get();
-  }
-
-  @Override
-  public boolean canAddBreakpoints() {
-    return true;
-  }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointPropertiesPanel.java
index bec1264..4d0bec2 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointPropertiesPanel.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointPropertiesPanel.java
@@ -21,24 +21,30 @@
 package com.intellij.debugger.ui.breakpoints;
 
 import com.intellij.debugger.DebuggerBundle;
-import com.intellij.openapi.project.Project;
 import com.intellij.ui.IdeBorderFactory;
 import com.intellij.util.ui.DialogUtil;
+import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaFieldBreakpointProperties;
 
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 
-public class FieldBreakpointPropertiesPanel extends BreakpointPropertiesPanel {
+public class FieldBreakpointPropertiesPanel extends XBreakpointCustomPropertiesPanel<XLineBreakpoint<JavaFieldBreakpointProperties>> {
   private JCheckBox myWatchAccessCheckBox;
   private JCheckBox myWatchModificationCheckBox;
 
-  public FieldBreakpointPropertiesPanel(final Project project, boolean compact) {
-    super(project, FieldBreakpoint.CATEGORY, compact);
-  }
+  //public FieldBreakpointPropertiesPanel(final Project project, boolean compact) {
+  //  super(project, FieldBreakpoint.CATEGORY, compact);
+  //}
 
-  protected JComponent createSpecialBox() {
+
+  @NotNull
+  @Override
+  public JComponent getComponent() {
     JPanel _panel;
     JPanel _panel0;
     myWatchAccessCheckBox = new JCheckBox(DebuggerBundle.message("label.filed.breakpoint.properties.panel.field.access"));
@@ -86,20 +92,15 @@
     return _panel;
   }
 
-  public void initFrom(Breakpoint breakpoint, boolean moreOptionsVisible) {
-    super.initFrom(breakpoint, moreOptionsVisible);
-    FieldBreakpoint fieldBreakpoint = (FieldBreakpoint)breakpoint;
-
-    myWatchAccessCheckBox.setSelected(fieldBreakpoint.WATCH_ACCESS);
-    myWatchModificationCheckBox.setSelected(fieldBreakpoint.WATCH_MODIFICATION);
+  @Override
+  public void loadFrom(@NotNull XLineBreakpoint<JavaFieldBreakpointProperties> breakpoint) {
+    myWatchAccessCheckBox.setSelected(breakpoint.getProperties().WATCH_ACCESS);
+    myWatchModificationCheckBox.setSelected(breakpoint.getProperties().WATCH_MODIFICATION);
   }
 
-  public void saveTo(Breakpoint breakpoint) {
-    FieldBreakpoint fieldBreakpoint = (FieldBreakpoint)breakpoint;
-
-    fieldBreakpoint.WATCH_ACCESS = myWatchAccessCheckBox.isSelected();
-    fieldBreakpoint.WATCH_MODIFICATION = myWatchModificationCheckBox.isSelected();
-
-    super.saveTo(breakpoint);
+  @Override
+  public void saveTo(@NotNull XLineBreakpoint<JavaFieldBreakpointProperties> breakpoint) {
+    breakpoint.getProperties().WATCH_ACCESS = myWatchAccessCheckBox.isSelected();
+    breakpoint.getProperties().WATCH_MODIFICATION = myWatchModificationCheckBox.isSelected();
   }
 }
\ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java
index 8aa57bd..6a628f1 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -13,250 +13,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/**
- * class FilteredRequestor
- * @author Jeka
- */
 package com.intellij.debugger.ui.breakpoints;
 
-import com.intellij.debugger.*;
-import com.intellij.debugger.engine.ContextUtil;
-import com.intellij.debugger.engine.DebugProcessImpl;
-import com.intellij.debugger.engine.evaluation.*;
-import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl;
-import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
+import com.intellij.debugger.InstanceFilter;
 import com.intellij.debugger.engine.requests.LocatableEventRequestor;
-import com.intellij.debugger.impl.DebuggerUtilsEx;
-import com.intellij.debugger.settings.DebuggerSettings;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.*;
-import com.intellij.psi.PsiElement;
 import com.intellij.ui.classFilter.ClassFilter;
-import com.sun.jdi.BooleanValue;
-import com.sun.jdi.ObjectReference;
-import com.sun.jdi.VMDisconnectedException;
-import com.sun.jdi.Value;
-import com.sun.jdi.event.LocatableEvent;
-import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
-import java.util.ArrayList;
-import java.util.List;
+/**
+ * @author egor
+ */
+public interface FilteredRequestor extends LocatableEventRequestor {
+  String getSuspendPolicy();
 
-public abstract class FilteredRequestor implements LocatableEventRequestor, JDOMExternalizable {
+  boolean isInstanceFiltersEnabled();
+  InstanceFilter[] getInstanceFilters();
 
-  public String  SUSPEND_POLICY = DebuggerSettings.SUSPEND_ALL;
-  public boolean  SUSPEND = true;
+  boolean isCountFilterEnabled();
+  int getCountFilter();
 
-  public boolean COUNT_FILTER_ENABLED     = false;
-  public int COUNT_FILTER = 0;
-
-  public boolean CONDITION_ENABLED        = false;
-  private TextWithImports myCondition;
-
-  public boolean CLASS_FILTERS_ENABLED    = false;
-  private ClassFilter[] myClassFilters          = ClassFilter.EMPTY_ARRAY;
-  private ClassFilter[] myClassExclusionFilters = ClassFilter.EMPTY_ARRAY;
-
-  public boolean INSTANCE_FILTERS_ENABLED = false;
-  private InstanceFilter[] myInstanceFilters  = InstanceFilter.EMPTY_ARRAY;
-
-  @NonNls private static final String FILTER_OPTION_NAME = "filter";
-  @NonNls private static final String EXCLUSION_FILTER_OPTION_NAME = "exclusion_filter";
-  @NonNls private static final String INSTANCE_ID_OPTION_NAME = "instance_id";
-  @NonNls private static final String CONDITION_OPTION_NAME = "CONDITION";
-  protected final Project myProject;
-
-  public FilteredRequestor(@NotNull Project project) {
-    myProject = project;
-    myCondition = new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "");
-  }
-
-  public InstanceFilter[] getInstanceFilters() {
-    return myInstanceFilters;
-  }
-
-  public void setInstanceFilters(InstanceFilter[] instanceFilters) {
-    myInstanceFilters = instanceFilters != null? instanceFilters : InstanceFilter.EMPTY_ARRAY;
-  }
-
-  public String getSuspendPolicy() {
-    return SUSPEND? SUSPEND_POLICY : DebuggerSettings.SUSPEND_NONE;
-  }
-
-  /**
-   * @return true if the ID was added or false otherwise
-   */
-  private boolean hasObjectID(long id) {
-    for (InstanceFilter instanceFilter : myInstanceFilters) {
-      if (instanceFilter.getId() == id) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  protected void addInstanceFilter(long l) {
-    final InstanceFilter[] filters = new InstanceFilter[myInstanceFilters.length + 1];
-    System.arraycopy(myInstanceFilters, 0, filters, 0, myInstanceFilters.length);
-    filters[myInstanceFilters.length] = InstanceFilter.create(String.valueOf(l));
-    myInstanceFilters = filters;
-  }
-
-  public final ClassFilter[] getClassFilters() {
-    return myClassFilters;
-  }
-
-  public final void setClassFilters(ClassFilter[] classFilters) {
-    myClassFilters = classFilters != null? classFilters : ClassFilter.EMPTY_ARRAY;
-  }
-
-  public ClassFilter[] getClassExclusionFilters() {
-    return myClassExclusionFilters;
-  }
-
-  public void setClassExclusionFilters(ClassFilter[] classExclusionFilters) {
-    myClassExclusionFilters = classExclusionFilters != null? classExclusionFilters : ClassFilter.EMPTY_ARRAY;
-  }
-
-  public void readExternal(Element parentNode) throws InvalidDataException {
-    DefaultJDOMExternalizer.readExternal(this, parentNode);
-    if (DebuggerSettings.SUSPEND_NONE.equals(SUSPEND_POLICY)) { // compatibility with older format
-      SUSPEND = false;
-      SUSPEND_POLICY = DebuggerSettings.SUSPEND_ALL;
-    }
-    String condition = JDOMExternalizerUtil.readField(parentNode, CONDITION_OPTION_NAME);
-    if (condition != null) {
-      setCondition(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, condition));
-    }
-
-    myClassFilters = DebuggerUtilsEx.readFilters(parentNode.getChildren(FILTER_OPTION_NAME));
-    myClassExclusionFilters = DebuggerUtilsEx.readFilters(parentNode.getChildren(EXCLUSION_FILTER_OPTION_NAME));
-
-    final ClassFilter [] instanceFilters = DebuggerUtilsEx.readFilters(parentNode.getChildren(INSTANCE_ID_OPTION_NAME));
-    final List<InstanceFilter> iFilters = new ArrayList<InstanceFilter>(instanceFilters.length);
-
-    for (ClassFilter instanceFilter : instanceFilters) {
-      try {
-        iFilters.add(InstanceFilter.create(instanceFilter));
-      }
-      catch (Exception e) {
-      }
-    }
-    myInstanceFilters = iFilters.isEmpty() ? InstanceFilter.EMPTY_ARRAY : iFilters.toArray(new InstanceFilter[iFilters.size()]);
-  }
-
-  public void writeExternal(Element parentNode) throws WriteExternalException {
-    DefaultJDOMExternalizer.writeExternal(this, parentNode);
-    JDOMExternalizerUtil.writeField(parentNode, CONDITION_OPTION_NAME, getCondition().toExternalForm());
-    DebuggerUtilsEx.writeFilters(parentNode, FILTER_OPTION_NAME, myClassFilters);
-    DebuggerUtilsEx.writeFilters(parentNode, EXCLUSION_FILTER_OPTION_NAME, myClassExclusionFilters);
-    DebuggerUtilsEx.writeFilters(parentNode, INSTANCE_ID_OPTION_NAME, InstanceFilter.createClassFilters(myInstanceFilters));
-  }
-
-  public boolean evaluateCondition(final EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
-    if(COUNT_FILTER_ENABLED) {
-      final DebugProcessImpl debugProcess = context.getDebugProcess();
-      debugProcess.getVirtualMachineProxy().suspend();
-      debugProcess.getRequestsManager().deleteRequest(this);
-      ((Breakpoint)this).createRequest(debugProcess);
-      debugProcess.getVirtualMachineProxy().resume();
-    }
-    if (INSTANCE_FILTERS_ENABLED) {
-      Value value = context.getThisObject();
-      if (value != null) {  // non-static
-        ObjectReference reference = (ObjectReference)value;
-        if(!hasObjectID(reference.uniqueID())) {
-          return false;
-        }
-      }
-    }
-
-    if (CLASS_FILTERS_ENABLED) {
-      String typeName = calculateEventClass(context, event);
-      if (!typeMatchesClassFilters(typeName)) return false;
-    }
-
-    if (CONDITION_ENABLED && getCondition() != null && !"".equals(getCondition().getText())) {
-      try {
-        ExpressionEvaluator evaluator = DebuggerInvocationUtil.commitAndRunReadAction(context.getProject(), new EvaluatingComputable<ExpressionEvaluator>() {
-          public ExpressionEvaluator compute() throws EvaluateException {
-            final SourcePosition contextSourcePosition = ContextUtil.getSourcePosition(context);
-            // IMPORTANT: calculate context psi element basing on the location where the exception
-            // has been hit, not on the location where it was set. (For line breakpoints these locations are the same, however, 
-            // for method, exception and field breakpoints these locations differ)
-            PsiElement contextPsiElement = ContextUtil.getContextElement(contextSourcePosition);
-            if (contextPsiElement == null) {
-              contextPsiElement = getEvaluationElement(); // as a last resort
-            }
-            return EvaluatorBuilderImpl.build(getCondition(), contextPsiElement, contextSourcePosition);
-          }
-        });
-        final Value value = evaluator.evaluate(context);
-        if (!(value instanceof BooleanValue)) {
-          throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.boolean.expected"));
-        }
-        if(!((BooleanValue)value).booleanValue()) {
-          return false;
-        }
-      }
-      catch (EvaluateException ex) {
-        if(ex.getCause() instanceof VMDisconnectedException) {
-          return false;
-        }
-        throw EvaluateExceptionUtil.createEvaluateException(
-          DebuggerBundle.message("error.failed.evaluating.breakpoint.condition", getCondition(), ex.getMessage())
-        );
-      }
-      return true;
-    }
-
-    return true;
-  }
-
-  protected String calculateEventClass(EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
-    return event.location().declaringType().name();
-  }
-
-  private boolean typeMatchesClassFilters(@Nullable String typeName) {
-    if (typeName == null) {
-      return true;
-    }
-    boolean matches = false, hasEnabled = false;
-    for (ClassFilter classFilter : getClassFilters()) {
-      if (classFilter.isEnabled()) {
-        hasEnabled = true;
-        if (classFilter.matches(typeName)) {
-          matches = true;
-          break;
-        }
-      }
-    }
-    if(hasEnabled && !matches) {
-      return false;
-    }
-    for (ClassFilter classFilter : getClassExclusionFilters()) {
-      if (classFilter.isEnabled() && classFilter.matches(typeName)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  public abstract PsiElement getEvaluationElement();
-
-  public TextWithImports getCondition() {
-    return myCondition;
-  }
-
-  public void setCondition(TextWithImports condition) {
-    myCondition = condition;
-  }
-
-  public Project getProject() {
-    return myProject;
-  }
+  boolean isClassFiltersEnabled();
+  ClassFilter[] getClassFilters();
+  ClassFilter[] getClassExclusionFilters();
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestorImpl.java
new file mode 100644
index 0000000..4962928
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestorImpl.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2000-2009 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.
+ */
+
+/**
+ * class FilteredRequestorImpl
+ * @author Jeka
+ */
+package com.intellij.debugger.ui.breakpoints;
+
+import com.intellij.debugger.InstanceFilter;
+import com.intellij.debugger.engine.evaluation.*;
+import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
+import com.intellij.debugger.impl.DebuggerUtilsEx;
+import com.intellij.debugger.settings.DebuggerSettings;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.*;
+import com.intellij.psi.PsiElement;
+import com.intellij.ui.classFilter.ClassFilter;
+import com.sun.jdi.event.LocatableEvent;
+import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * Not used any more, since move to xBreakpoints
+ */
+public class FilteredRequestorImpl implements JDOMExternalizable, FilteredRequestor {
+
+  public String  SUSPEND_POLICY = DebuggerSettings.SUSPEND_ALL;
+  public boolean  SUSPEND = true;
+
+  public boolean COUNT_FILTER_ENABLED     = false;
+  public int COUNT_FILTER = 0;
+
+  public boolean CONDITION_ENABLED        = false;
+  private TextWithImports myCondition;
+
+  public boolean CLASS_FILTERS_ENABLED    = false;
+  private ClassFilter[] myClassFilters          = ClassFilter.EMPTY_ARRAY;
+  private ClassFilter[] myClassExclusionFilters = ClassFilter.EMPTY_ARRAY;
+
+  public boolean INSTANCE_FILTERS_ENABLED = false;
+  private InstanceFilter[] myInstanceFilters  = InstanceFilter.EMPTY_ARRAY;
+
+  @NonNls private static final String FILTER_OPTION_NAME = "filter";
+  @NonNls private static final String EXCLUSION_FILTER_OPTION_NAME = "exclusion_filter";
+  @NonNls private static final String INSTANCE_ID_OPTION_NAME = "instance_id";
+  @NonNls private static final String CONDITION_OPTION_NAME = "CONDITION";
+  protected final Project myProject;
+
+  public FilteredRequestorImpl(@NotNull Project project) {
+    myProject = project;
+    myCondition = new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "");
+  }
+
+  public InstanceFilter[] getInstanceFilters() {
+    return myInstanceFilters;
+  }
+
+  public void setInstanceFilters(InstanceFilter[] instanceFilters) {
+    myInstanceFilters = instanceFilters != null? instanceFilters : InstanceFilter.EMPTY_ARRAY;
+  }
+
+  public String getSuspendPolicy() {
+    return SUSPEND? SUSPEND_POLICY : DebuggerSettings.SUSPEND_NONE;
+  }
+
+  /**
+   * @return true if the ID was added or false otherwise
+   */
+  private boolean hasObjectID(long id) {
+    for (InstanceFilter instanceFilter : myInstanceFilters) {
+      if (instanceFilter.getId() == id) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  protected void addInstanceFilter(long l) {
+    final InstanceFilter[] filters = new InstanceFilter[myInstanceFilters.length + 1];
+    System.arraycopy(myInstanceFilters, 0, filters, 0, myInstanceFilters.length);
+    filters[myInstanceFilters.length] = InstanceFilter.create(String.valueOf(l));
+    myInstanceFilters = filters;
+  }
+
+  public final ClassFilter[] getClassFilters() {
+    return myClassFilters;
+  }
+
+  public final void setClassFilters(ClassFilter[] classFilters) {
+    myClassFilters = classFilters != null? classFilters : ClassFilter.EMPTY_ARRAY;
+  }
+
+  public ClassFilter[] getClassExclusionFilters() {
+    return myClassExclusionFilters;
+  }
+
+  public void setClassExclusionFilters(ClassFilter[] classExclusionFilters) {
+    myClassExclusionFilters = classExclusionFilters != null? classExclusionFilters : ClassFilter.EMPTY_ARRAY;
+  }
+
+  public void readTo(Element parentNode, Breakpoint breakpoint) throws InvalidDataException {
+    readExternal(parentNode);
+    if (SUSPEND) {
+      breakpoint.setSuspendPolicy(SUSPEND_POLICY);
+    }
+    else {
+      breakpoint.setSuspendPolicy(DebuggerSettings.SUSPEND_NONE);
+    }
+
+    breakpoint.setCountFilterEnabled(COUNT_FILTER_ENABLED);
+    breakpoint.setCountFilter(COUNT_FILTER);
+
+    breakpoint.setCondition(CONDITION_ENABLED ? myCondition : null);
+
+    breakpoint.setClassFiltersEnabled(CLASS_FILTERS_ENABLED);
+    breakpoint.setClassFilters(getClassFilters());
+    breakpoint.setClassExclusionFilters(getClassExclusionFilters());
+
+    breakpoint.setInstanceFiltersEnabled(INSTANCE_FILTERS_ENABLED);
+    breakpoint.setInstanceFilters(getInstanceFilters());
+  }
+
+  public void readExternal(Element parentNode) throws InvalidDataException {
+    DefaultJDOMExternalizer.readExternal(this, parentNode);
+    if (DebuggerSettings.SUSPEND_NONE.equals(SUSPEND_POLICY)) { // compatibility with older format
+      SUSPEND = false;
+      SUSPEND_POLICY = DebuggerSettings.SUSPEND_ALL;
+    }
+    String condition = JDOMExternalizerUtil.readField(parentNode, CONDITION_OPTION_NAME);
+    if (condition != null) {
+      setCondition(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, condition));
+    }
+
+    myClassFilters = DebuggerUtilsEx.readFilters(parentNode.getChildren(FILTER_OPTION_NAME));
+    myClassExclusionFilters = DebuggerUtilsEx.readFilters(parentNode.getChildren(EXCLUSION_FILTER_OPTION_NAME));
+
+    final ClassFilter [] instanceFilters = DebuggerUtilsEx.readFilters(parentNode.getChildren(INSTANCE_ID_OPTION_NAME));
+    final List<InstanceFilter> iFilters = new ArrayList<InstanceFilter>(instanceFilters.length);
+
+    for (ClassFilter instanceFilter : instanceFilters) {
+      try {
+        iFilters.add(InstanceFilter.create(instanceFilter));
+      }
+      catch (Exception e) {
+      }
+    }
+    myInstanceFilters = iFilters.isEmpty() ? InstanceFilter.EMPTY_ARRAY : iFilters.toArray(new InstanceFilter[iFilters.size()]);
+  }
+
+  public void writeExternal(Element parentNode) throws WriteExternalException {
+    DefaultJDOMExternalizer.writeExternal(this, parentNode);
+    JDOMExternalizerUtil.writeField(parentNode, CONDITION_OPTION_NAME, getCondition().toExternalForm());
+    DebuggerUtilsEx.writeFilters(parentNode, FILTER_OPTION_NAME, myClassFilters);
+    DebuggerUtilsEx.writeFilters(parentNode, EXCLUSION_FILTER_OPTION_NAME, myClassExclusionFilters);
+    DebuggerUtilsEx.writeFilters(parentNode, INSTANCE_ID_OPTION_NAME, InstanceFilter.createClassFilters(myInstanceFilters));
+  }
+
+  protected String calculateEventClass(EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
+    return event.location().declaringType().name();
+  }
+
+  private boolean typeMatchesClassFilters(@Nullable String typeName) {
+    if (typeName == null) {
+      return true;
+    }
+    boolean matches = false, hasEnabled = false;
+    for (ClassFilter classFilter : getClassFilters()) {
+      if (classFilter.isEnabled()) {
+        hasEnabled = true;
+        if (classFilter.matches(typeName)) {
+          matches = true;
+          break;
+        }
+      }
+    }
+    if(hasEnabled && !matches) {
+      return false;
+    }
+    for (ClassFilter classFilter : getClassExclusionFilters()) {
+      if (classFilter.isEnabled() && classFilter.matches(typeName)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public PsiElement getEvaluationElement() {
+    return null;
+  }
+
+  public TextWithImports getCondition() {
+    return myCondition;
+  }
+
+  public void setCondition(TextWithImports condition) {
+    myCondition = condition;
+  }
+
+  public Project getProject() {
+    return myProject;
+  }
+
+  public boolean isCountFilterEnabled() {
+    return COUNT_FILTER_ENABLED;
+  }
+
+  public int getCountFilter() {
+    return COUNT_FILTER;
+  }
+
+  public boolean isClassFiltersEnabled() {
+    return CLASS_FILTERS_ENABLED;
+  }
+
+  public boolean isInstanceFiltersEnabled() {
+    return INSTANCE_FILTERS_ENABLED;
+  }
+
+  @Override
+  public boolean processLocatableEvent(SuspendContextCommandImpl action, LocatableEvent event)
+    throws EventProcessingException {
+    return false;
+  }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java
deleted file mode 100644
index ec3577c..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.ui.breakpoints;
-
-import com.intellij.debugger.DebuggerManagerEx;
-import com.intellij.debugger.SourcePosition;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.SimpleColoredComponent;
-import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.ui.popup.util.DetailView;
-import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointItem;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-
-class JavaBreakpointItem extends BreakpointItem {
-  private final Breakpoint myBreakpoint;
-  private BreakpointFactory myBreakpointFactory;
-  private BreakpointPropertiesPanel myBreakpointPropertiesPanel;
-
-  public JavaBreakpointItem(@Nullable BreakpointFactory breakpointFactory, Breakpoint breakpoint) {
-    myBreakpointFactory = breakpointFactory;
-    myBreakpoint = breakpoint;
-  }
-
-  @Override
-  public void setupGenericRenderer(SimpleColoredComponent renderer, boolean plainView) {
-    if (plainView) {
-      renderer.setIcon(myBreakpoint.getIcon());
-    }
-    renderer.append(plainView ? StringUtil.shortenTextWithEllipsis(myBreakpoint.getShortName(), 60, 0) : myBreakpoint.getDisplayName(),
-                    isEnabled() ? SimpleTextAttributes.REGULAR_ATTRIBUTES : SimpleTextAttributes.GRAY_ATTRIBUTES);
-  }
-
-  @Override
-  public Icon getIcon() {
-    return myBreakpoint.getIcon();
-  }
-
-  @Override
-  public String getDisplayText() {
-    return myBreakpoint.getDisplayName();
-  }
-
-  @Override
-  public String speedSearchText() {
-    return myBreakpoint.getDisplayName();
-  }
-
-  @Override
-  public String footerText() {
-    return myBreakpoint.getDisplayName();
-  }
-
-  @Override
-  protected void doUpdateDetailView(DetailView panel, boolean editorOnly) {
-    //saveState();
-    if (myBreakpointPropertiesPanel != null) {
-      myBreakpointPropertiesPanel.dispose();
-      myBreakpointPropertiesPanel = null;
-    }
-
-    if (!editorOnly) {
-      myBreakpointPropertiesPanel = myBreakpointFactory != null ? myBreakpointFactory
-        .createBreakpointPropertiesPanel(myBreakpoint.getProject(), false) : null;
-
-      if (myBreakpointPropertiesPanel != null) {
-        myBreakpointPropertiesPanel.initFrom(myBreakpoint, true);
-
-        final JPanel mainPanel = myBreakpointPropertiesPanel.getPanel();
-        panel.setPropertiesPanel(mainPanel);
-      }
-      else {
-        panel.setPropertiesPanel(null);
-      }
-    }
-
-    if (myBreakpoint instanceof BreakpointWithHighlighter) {
-      SourcePosition sourcePosition = ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition();
-      VirtualFile virtualFile = sourcePosition.getFile().getVirtualFile();
-      showInEditor(panel, virtualFile, sourcePosition.getLine());
-    } else {
-      panel.clearEditor();
-    }
-    if (myBreakpointPropertiesPanel != null) {
-      myBreakpointPropertiesPanel.setDetailView(panel);
-    }
-  }
-
-  @Override
-  public void navigate(boolean requestFocus) {
-    if (myBreakpoint instanceof BreakpointWithHighlighter) {
-      ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition().navigate(requestFocus);
-    }
-  }
-
-  @Override
-  public boolean canNavigate() {
-    return myBreakpoint instanceof BreakpointWithHighlighter && ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition().canNavigate();
-  }
-
-  @Override
-  public boolean canNavigateToSource() {
-    return myBreakpoint instanceof BreakpointWithHighlighter &&
-           ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition().canNavigateToSource();
-  }
-
-  @Override
-  public boolean allowedToRemove() {
-    return myBreakpointFactory != null && myBreakpointFactory.breakpointCanBeRemoved(myBreakpoint);
-  }
-
-  @Override
-  public void removed(Project project) {
-    dispose();
-    DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().removeBreakpoint(myBreakpoint);
-  }
-
-  @Override
-  public void saveState() {
-    if (myBreakpointPropertiesPanel != null) {
-      myBreakpointPropertiesPanel.saveTo(myBreakpoint);
-    }
-  }
-
-  @Override
-  public Object getBreakpoint() {
-    return myBreakpoint;
-  }
-
-  @Override
-  public boolean isEnabled() {
-    return myBreakpoint.ENABLED;
-  }
-
-  @Override
-  public void setEnabled(boolean state) {
-    myBreakpoint.ENABLED = state;
-    myBreakpoint.updateUI();
-    DebuggerManagerEx.getInstanceEx(myBreakpoint.getProject()).getBreakpointManager().fireBreakpointChanged(myBreakpoint);
-  }
-
-  @Override
-  public boolean isDefaultBreakpoint() {
-    return myBreakpoint.getCategory().equals(ExceptionBreakpoint.CATEGORY);
-  }
-
-  @Override
-  protected void dispose() {
-    if (myBreakpointPropertiesPanel != null) {
-      myBreakpointPropertiesPanel.dispose();
-      myBreakpointPropertiesPanel = null;
-    }
-  }
-
-  @Override
-  public int compareTo(@NotNull BreakpointItem breakpointItem) {
-    final Object breakpoint = breakpointItem.getBreakpoint();
-    if (breakpoint instanceof Breakpoint) {
-      return -getIndexOf(myBreakpoint) + getIndexOf((Breakpoint)breakpoint);
-    }
-    return getDisplayText().compareTo(breakpointItem.getDisplayText());
-  }
-
-  private int getIndexOf(Breakpoint breakpoint) {
-    return DebuggerManagerEx.getInstanceEx(myBreakpoint.getProject()).getBreakpointManager().getBreakpoints().indexOf(breakpoint);
-  }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointType.java
similarity index 62%
rename from java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpointPropertiesPanel.java
rename to java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointType.java
index 802657b..2776032 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpointPropertiesPanel.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -13,17 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/*
- * Class LineBreakpointPropertiesPanel
- * @author Jeka
- */
 package com.intellij.debugger.ui.breakpoints;
 
 import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;
 
-public class LineBreakpointPropertiesPanel extends BreakpointPropertiesPanel {
-  public LineBreakpointPropertiesPanel(Project project, boolean compact) {
-    super(project, LineBreakpoint.CATEGORY, compact);
-  }
-}
\ No newline at end of file
+/**
+ * Base class for all Java breakpoint types
+ * @author egor
+ */
+public interface JavaBreakpointType<P extends JavaBreakpointProperties> {
+  Breakpoint createJavaBreakpoint(Project project, XBreakpoint<P> breakpoint);
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java
new file mode 100644
index 0000000..0bb20d6
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.ui.breakpoints;
+
+import com.intellij.debugger.DebuggerManagerEx;
+import com.intellij.debugger.ui.JavaDebuggerSupport;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiClass;
+import com.intellij.xdebugger.XDebuggerUtil;
+import com.intellij.xdebugger.XSourcePosition;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.XBreakpointType;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.JavaDebuggerEditorsProvider;
+import org.jetbrains.java.debugger.breakpoints.JavaBreakpointFiltersPanel;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;
+
+/**
+ * Base class for non-line java breakpoint
+ * @author egor
+ */
+public abstract class JavaBreakpointTypeBase<T extends JavaBreakpointProperties> extends XBreakpointType<XBreakpoint<T>, T> {
+  protected JavaBreakpointTypeBase(@NonNls @NotNull String id, @Nls @NotNull String title) {
+    super(id, title, true);
+  }
+
+  @Override
+  public final boolean isAddBreakpointButtonVisible() {
+    return true;
+  }
+
+  @Nullable
+  @Override
+  public final XBreakpointCustomPropertiesPanel<XBreakpoint<T>> createCustomRightPropertiesPanel(@NotNull Project project) {
+    return new JavaBreakpointFiltersPanel<T, XBreakpoint<T>>(project);
+  }
+
+  @Nullable
+  @Override
+  public final XDebuggerEditorsProvider getEditorsProvider(@NotNull XBreakpoint<T> breakpoint, @NotNull Project project) {
+    return new JavaDebuggerEditorsProvider();
+  }
+
+  @Nullable
+  @Override
+  public XSourcePosition getSourcePosition(@NotNull XBreakpoint<T> breakpoint) {
+    BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(JavaDebuggerSupport.getCurrentProject()).getBreakpointManager();
+    Breakpoint javaBreakpoint = breakpointManager.findBreakpoint(breakpoint);
+    if (javaBreakpoint != null) {
+      PsiClass aClass = javaBreakpoint.getPsiClass();
+      if (aClass != null && aClass.getContainingFile() != null) {
+        return XDebuggerUtil.getInstance().createPositionByOffset(aClass.getContainingFile().getVirtualFile(), aClass.getTextOffset());
+      }
+    }
+    return null;
+  }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaExceptionBreakpointType.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaExceptionBreakpointType.java
new file mode 100644
index 0000000..d5d4b71
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaExceptionBreakpointType.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.ui.breakpoints;
+
+import com.intellij.debugger.DebuggerBundle;
+import com.intellij.debugger.HelpID;
+import com.intellij.debugger.engine.JVMNameUtil;
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.util.TreeClassChooser;
+import com.intellij.ide.util.TreeClassChooserFactory;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiClassOwner;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.xdebugger.XDebuggerManager;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaExceptionBreakpointProperties;
+
+import javax.swing.*;
+
+/**
+ * @author Eugene Zhuravlev
+ *         Date: Apr 26, 2005
+ */
+public class JavaExceptionBreakpointType extends JavaBreakpointTypeBase<JavaExceptionBreakpointProperties>
+                                         implements JavaBreakpointType<JavaExceptionBreakpointProperties> {
+  public JavaExceptionBreakpointType() {
+    super("java-exception", DebuggerBundle.message("exception.breakpoints.tab.title"));
+  }
+
+  @NotNull
+  @Override
+  public Icon getEnabledIcon() {
+    return AllIcons.Debugger.Db_exception_breakpoint;
+  }
+
+  @NotNull
+  @Override
+  public Icon getDisabledIcon() {
+    return AllIcons.Debugger.Db_disabled_exception_breakpoint;
+  }
+
+  //@Override
+  protected String getHelpID() {
+    return HelpID.EXCEPTION_BREAKPOINTS;
+  }
+
+  //@Override
+  public String getDisplayName() {
+    return DebuggerBundle.message("exception.breakpoints.tab.title");
+  }
+
+  @Override
+  public String getDisplayText(XBreakpoint<JavaExceptionBreakpointProperties> breakpoint) {
+    String name = breakpoint.getProperties().myQualifiedName;
+    if (name != null) {
+      return DebuggerBundle.message("breakpoint.exception.breakpoint.display.name", name);
+    }
+    else {
+      return DebuggerBundle.message("breakpoint.any.exception.display.name");
+    }
+  }
+
+  @Nullable
+  @Override
+  public JavaExceptionBreakpointProperties createProperties() {
+    return new JavaExceptionBreakpointProperties();
+  }
+
+  @Nullable
+  @Override
+  public XBreakpointCustomPropertiesPanel<XBreakpoint<JavaExceptionBreakpointProperties>> createCustomPropertiesPanel() {
+    return new ExceptionBreakpointPropertiesPanel();
+  }
+
+  @Nullable
+  @Override
+  public XBreakpoint<JavaExceptionBreakpointProperties> createDefaultBreakpoint(@NotNull XBreakpointCreator<JavaExceptionBreakpointProperties> creator) {
+    return creator.createBreakpoint(new JavaExceptionBreakpointProperties());
+  }
+
+  //public Key<ExceptionBreakpoint> getBreakpointCategory() {
+  //  return ExceptionBreakpoint.CATEGORY;
+  //}
+
+  @Nullable
+  @Override
+  public XBreakpoint<JavaExceptionBreakpointProperties> addBreakpoint(final Project project, JComponent parentComponent) {
+    final PsiClass throwableClass =
+      JavaPsiFacade.getInstance(project).findClass("java.lang.Throwable", GlobalSearchScope.allScope(project));
+    TreeClassChooser chooser = TreeClassChooserFactory.getInstance(project)
+      .createInheritanceClassChooser(DebuggerBundle.message("add.exception.breakpoint.classchooser.title"),
+                                     GlobalSearchScope.allScope(project), throwableClass, true, true, null);
+    chooser.showDialog();
+    final PsiClass selectedClass = chooser.getSelected();
+    final String qName = selectedClass == null ? null : JVMNameUtil.getNonAnonymousClassName(selectedClass);
+
+    if (qName != null && qName.length() > 0) {
+      return ApplicationManager.getApplication().runWriteAction(new Computable<XBreakpoint<JavaExceptionBreakpointProperties>>() {
+       @Override
+       public XBreakpoint<JavaExceptionBreakpointProperties> compute() {
+         return XDebuggerManager.getInstance(project).getBreakpointManager().addBreakpoint(
+           JavaExceptionBreakpointType.this, new JavaExceptionBreakpointProperties(qName, ((PsiClassOwner)selectedClass.getContainingFile()).getPackageName()));
+       }
+     });
+    }
+    return null;
+  }
+
+  @Override
+  public Breakpoint createJavaBreakpoint(Project project, XBreakpoint<JavaExceptionBreakpointProperties> breakpoint) {
+    if (!XDebuggerManager.getInstance(project).getBreakpointManager().isDefaultBreakpoint(breakpoint)) {
+      return new ExceptionBreakpoint(project, breakpoint);
+    }
+    else {
+      return new AnyExceptionBreakpoint(project, breakpoint);
+    }
+  }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaFieldBreakpointType.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaFieldBreakpointType.java
new file mode 100644
index 0000000..74a6f2d
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaFieldBreakpointType.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.ui.breakpoints;
+
+import com.intellij.CommonBundle;
+import com.intellij.debugger.DebuggerBundle;
+import com.intellij.debugger.HelpID;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.xdebugger.XDebuggerManager;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaFieldBreakpointProperties;
+
+import javax.swing.*;
+
+/**
+ * @author Eugene Zhuravlev
+ *         Date: Apr 26, 2005
+ */
+public class JavaFieldBreakpointType extends JavaLineBreakpointTypeBase<JavaFieldBreakpointProperties> implements JavaBreakpointType {
+  public JavaFieldBreakpointType() {
+    super("java-field", DebuggerBundle.message("field.watchpoints.tab.title"));
+  }
+
+  @NotNull
+  @Override
+  public Icon getEnabledIcon() {
+    return AllIcons.Debugger.Db_field_breakpoint;
+  }
+
+  @NotNull
+  @Override
+  public Icon getDisabledIcon() {
+    return AllIcons.Debugger.Db_disabled_field_breakpoint;
+  }
+
+  //@Override
+  protected String getHelpID() {
+    return HelpID.FIELD_WATCHPOINTS;
+  }
+
+  //@Override
+  public String getDisplayName() {
+    return DebuggerBundle.message("field.watchpoints.tab.title");
+  }
+
+  @Override
+  public String getShortText(XLineBreakpoint<JavaFieldBreakpointProperties> breakpoint) {
+    return getText(breakpoint);
+  }
+
+  public String getText(XLineBreakpoint<JavaFieldBreakpointProperties> breakpoint) {
+    //if(!isValid()) {
+    //  return DebuggerBundle.message("status.breakpoint.invalid");
+    //}
+
+    JavaFieldBreakpointProperties properties = breakpoint.getProperties();
+    final String className = properties.myClassName;
+    return className != null && !className.isEmpty() ? className + "." + properties.myFieldName : properties.myFieldName;
+  }
+
+  @Nullable
+  @Override
+  public XBreakpointCustomPropertiesPanel<XLineBreakpoint<JavaFieldBreakpointProperties>> createCustomPropertiesPanel() {
+    return new FieldBreakpointPropertiesPanel();
+  }
+
+  @Nullable
+  @Override
+  public JavaFieldBreakpointProperties createProperties() {
+    return new JavaFieldBreakpointProperties();
+  }
+
+  @Nullable
+  @Override
+  public JavaFieldBreakpointProperties createBreakpointProperties(@NotNull VirtualFile file, int line) {
+    return new JavaFieldBreakpointProperties();
+  }
+
+  @Nullable
+  @Override
+  public XLineBreakpoint<JavaFieldBreakpointProperties> addBreakpoint(final Project project, JComponent parentComponent) {
+    final Ref<XLineBreakpoint> result = Ref.create(null);
+    AddFieldBreakpointDialog dialog = new AddFieldBreakpointDialog(project) {
+      protected boolean validateData() {
+        final String className = getClassName();
+        if (className.length() == 0) {
+          Messages.showMessageDialog(project, DebuggerBundle.message("error.field.breakpoint.class.name.not.specified"),
+                                     DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon());
+          return false;
+        }
+        final String fieldName = getFieldName();
+        if (fieldName.length() == 0) {
+          Messages.showMessageDialog(project, DebuggerBundle.message("error.field.breakpoint.field.name.not.specified"),
+                                     DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon());
+          return false;
+        }
+        PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(className, GlobalSearchScope.allScope(project));
+        if (psiClass != null) {
+          final PsiFile psiFile  = psiClass.getContainingFile();
+          Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
+          if(document != null) {
+            PsiField field = psiClass.findFieldByName(fieldName, true);
+            if(field != null) {
+              final int line = document.getLineNumber(field.getTextOffset());
+              ApplicationManager.getApplication().runWriteAction(new Runnable() {
+                @Override
+                public void run() {
+                  XLineBreakpoint<JavaFieldBreakpointProperties> fieldBreakpoint = XDebuggerManager.getInstance(project).getBreakpointManager()
+                    .addLineBreakpoint(JavaFieldBreakpointType.this, psiFile.getVirtualFile().getUrl(), line, new JavaFieldBreakpointProperties(fieldName, className));
+                  result.set(fieldBreakpoint);
+                }
+              });
+              return true;
+            }
+            else {
+              Messages.showMessageDialog(project,
+                                         DebuggerBundle.message("error.field.breakpoint.field.not.found", className, fieldName, fieldName),
+                                         CommonBundle.getErrorTitle(),
+                                         Messages.getErrorIcon()
+              );
+            }
+          }
+        } else {
+          Messages.showMessageDialog(project,
+                                     DebuggerBundle.message("error.field.breakpoint.class.sources.not.found", className, fieldName, className),
+                                     CommonBundle.getErrorTitle(),
+                                     Messages.getErrorIcon()
+          );
+        }
+        return false;
+      }
+    };
+    dialog.show();
+    return result.get();
+  }
+
+  @Override
+  public Breakpoint createJavaBreakpoint(Project project, XBreakpoint breakpoint) {
+    return new FieldBreakpoint(project, breakpoint);
+  }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointType.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointType.java
new file mode 100644
index 0000000..99a37d4
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointType.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.ui.breakpoints;
+
+import com.intellij.debugger.DebuggerBundle;
+import com.intellij.debugger.HelpID;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.xdebugger.XDebuggerUtil;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties;
+
+import javax.swing.*;
+import java.util.List;
+
+/**
+ * Base class for java line-connected exceptions (line, method, field)
+ * @author egor
+ */
+public class JavaLineBreakpointType extends JavaLineBreakpointTypeBase<JavaBreakpointProperties> implements JavaBreakpointType {
+  public JavaLineBreakpointType() {
+    super("java-line", DebuggerBundle.message("line.breakpoints.tab.title"));
+  }
+
+  @NotNull
+  @Override
+  public Icon getEnabledIcon() {
+    return AllIcons.Debugger.Db_set_breakpoint;
+  }
+
+  @NotNull
+  @Override
+  public Icon getDisabledIcon() {
+    return AllIcons.Debugger.Db_disabled_breakpoint;
+  }
+
+  //@Override
+  protected String getHelpID() {
+    return HelpID.LINE_BREAKPOINTS;
+  }
+
+  //@Override
+  public String getDisplayName() {
+    return DebuggerBundle.message("line.breakpoints.tab.title");
+  }
+
+  @Override
+  public List<XBreakpointGroupingRule<XLineBreakpoint<JavaBreakpointProperties>, ?>> getGroupingRules() {
+    return XDebuggerUtil.getInstance().getGroupingByFileRuleAsList();
+  }
+
+  @Nullable
+  @Override
+  public JavaBreakpointProperties createProperties() {
+    return new JavaLineBreakpointProperties();
+  }
+
+  @Nullable
+  @Override
+  public JavaBreakpointProperties createBreakpointProperties(@NotNull VirtualFile file, int line) {
+    return new JavaLineBreakpointProperties();
+  }
+
+  @Override
+  public Breakpoint createJavaBreakpoint(Project project, XBreakpoint breakpoint) {
+    return new LineBreakpoint(project, breakpoint);
+  }
+
+  @Override
+  public int getPriority() {
+    return 100;
+  }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointTypeBase.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointTypeBase.java
new file mode 100644
index 0000000..08b26bb
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointTypeBase.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.ui.breakpoints;
+
+import com.intellij.debugger.DebuggerManagerEx;
+import com.intellij.debugger.engine.DebuggerUtils;
+import com.intellij.debugger.ui.JavaDebuggerSupport;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.Processor;
+import com.intellij.xdebugger.XDebuggerUtil;
+import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.intellij.xdebugger.breakpoints.XLineBreakpointType;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.JavaDebuggerEditorsProvider;
+import org.jetbrains.java.debugger.breakpoints.JavaBreakpointFiltersPanel;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;
+
+/**
+ * Base class for java line-connected exceptions (line, method, field)
+ * @author egor
+ */
+public abstract class JavaLineBreakpointTypeBase<P extends JavaBreakpointProperties> extends XLineBreakpointType<P> {
+  public JavaLineBreakpointTypeBase(@NonNls @NotNull String id, @Nls @NotNull String title) {
+    super(id, title);
+  }
+
+  @Override
+  public boolean isAddBreakpointButtonVisible() {
+    return true;
+  }
+
+  @Override
+  public final boolean isSuspendThreadSupported() {
+    return true;
+  }
+
+  @Nullable
+  @Override
+  public final XBreakpointCustomPropertiesPanel<XLineBreakpoint<P>> createCustomRightPropertiesPanel(@NotNull Project project) {
+    return new JavaBreakpointFiltersPanel<P, XLineBreakpoint<P>>(project);
+  }
+
+  @Nullable
+  @Override
+  public final XDebuggerEditorsProvider getEditorsProvider(@NotNull XLineBreakpoint<P> breakpoint, @NotNull Project project) {
+    return new JavaDebuggerEditorsProvider();
+  }
+
+  @Override
+  public String getDisplayText(XLineBreakpoint<P> breakpoint) {
+    BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(JavaDebuggerSupport.getCurrentProject()).getBreakpointManager();
+      BreakpointWithHighlighter javaBreakpoint = (BreakpointWithHighlighter)breakpointManager.findBreakpoint(breakpoint);
+      if (javaBreakpoint != null) {
+        return javaBreakpoint.getDescription();
+      }
+      else {
+        return super.getDisplayText(breakpoint);
+      }
+  }
+
+  @Override
+  public final boolean canPutAt(@NotNull VirtualFile file, final int line, @NotNull Project project) {
+    PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
+    // JSPX supports jvm debugging, but not in XHTML files
+    // JS has it's own breakpoints
+    if (psiFile == null || psiFile.getVirtualFile().getFileType() == StdFileTypes.XHTML || psiFile.getVirtualFile().getFileType() == StdFileTypes.JS) {
+      return false;
+    }
+
+    FileType fileType = psiFile.getFileType();
+    if (!StdFileTypes.CLASS.equals(fileType) &&
+        !DebuggerUtils.supportsJVMDebugging(fileType) &&
+        !DebuggerUtils.supportsJVMDebugging(psiFile)) {
+      return false;
+    }
+
+    final Document document = FileDocumentManager.getInstance().getDocument(file);
+    final Ref<Class<? extends JavaLineBreakpointTypeBase>> result = Ref.create();
+    XDebuggerUtil.getInstance().iterateLine(project, document, line, new Processor<PsiElement>() {
+      @Override
+      public boolean process(PsiElement element) {
+        // avoid comments
+        if ((element instanceof PsiWhiteSpace) || (PsiTreeUtil.getParentOfType(element, PsiComment.class, false) != null)) {
+          return true;
+        }
+        PsiElement parent = element;
+        while(element != null) {
+          // skip modifiers
+          if (element instanceof PsiModifierList) {
+            element = element.getParent();
+            continue;
+          }
+
+          final int offset = element.getTextOffset();
+          if (offset >= 0) {
+            if (document.getLineNumber(offset) != line) {
+              break;
+            }
+          }
+          parent = element;
+          element = element.getParent();
+        }
+
+        if(parent instanceof PsiMethod) {
+          if (parent.getTextRange().getEndOffset() >= document.getLineEndOffset(line)) {
+            PsiCodeBlock body = ((PsiMethod)parent).getBody();
+            if (body != null) {
+              PsiStatement[] statements = body.getStatements();
+              if (statements.length > 0 && document.getLineNumber(statements[0].getTextOffset()) == line) {
+                result.set(JavaLineBreakpointType.class);
+              }
+            }
+          }
+          if (result.isNull()) {
+            result.set(JavaMethodBreakpointType.class);
+          }
+        }
+        else if (parent instanceof PsiField) {
+          if (result.isNull()) {
+            result.set(JavaFieldBreakpointType.class);
+          }
+        }
+        else {
+          result.set(JavaLineBreakpointType.class);
+        }
+        return true;
+      }
+    });
+    return result.get() == getClass();
+  }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaMethodBreakpointType.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaMethodBreakpointType.java
new file mode 100644
index 0000000..94c3c77
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaMethodBreakpointType.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.ui.breakpoints;
+
+import com.intellij.debugger.DebuggerBundle;
+import com.intellij.debugger.HelpID;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.StringBuilderSpinAllocator;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaMethodBreakpointProperties;
+
+import javax.swing.*;
+
+/**
+ * @author Eugene Zhuravlev
+ *         Date: Apr 26, 2005
+ */
+public class JavaMethodBreakpointType extends JavaLineBreakpointTypeBase<JavaMethodBreakpointProperties> implements JavaBreakpointType {
+  public JavaMethodBreakpointType() {
+    super("java-method", DebuggerBundle.message("method.breakpoints.tab.title"));
+  }
+
+  @NotNull
+  @Override
+  public Icon getEnabledIcon() {
+    return AllIcons.Debugger.Db_method_breakpoint;
+  }
+
+  @NotNull
+  @Override
+  public Icon getDisabledIcon() {
+    return AllIcons.Debugger.Db_disabled_method_breakpoint;
+  }
+
+  //@Override
+  protected String getHelpID() {
+    return HelpID.METHOD_BREAKPOINTS;
+  }
+
+  @Override
+  public boolean isAddBreakpointButtonVisible() {
+    return false;
+  }
+
+  //@Override
+  public String getDisplayName() {
+    return DebuggerBundle.message("method.breakpoints.tab.title");
+  }
+
+  @Override
+  public String getShortText(XLineBreakpoint<JavaMethodBreakpointProperties> breakpoint) {
+    return getText(breakpoint);
+  }
+
+  static String getText(XBreakpoint<JavaMethodBreakpointProperties> breakpoint) {
+    final StringBuilder buffer = StringBuilderSpinAllocator.alloc();
+    try {
+      //if(isValid()) {
+      final String className = breakpoint.getProperties().myClassPattern;
+      final boolean classNameExists = className != null && className.length() > 0;
+      if (classNameExists) {
+        buffer.append(className);
+      }
+      if(breakpoint.getProperties().myMethodName != null) {
+        if (classNameExists) {
+          buffer.append(".");
+        }
+        buffer.append(breakpoint.getProperties().myMethodName);
+      }
+      //}
+      //else {
+      //  buffer.append(DebuggerBundle.message("status.breakpoint.invalid"));
+      //}
+      return buffer.toString();
+    }
+    finally {
+      StringBuilderSpinAllocator.dispose(buffer);
+    }
+  }
+
+  @Nullable
+  @Override
+  public XBreakpointCustomPropertiesPanel createCustomPropertiesPanel() {
+    return new MethodBreakpointPropertiesPanel();
+  }
+
+  @Nullable
+  @Override
+  public JavaMethodBreakpointProperties createProperties() {
+    return new JavaMethodBreakpointProperties();
+  }
+
+  @Nullable
+  @Override
+  public JavaMethodBreakpointProperties createBreakpointProperties(@NotNull VirtualFile file, int line) {
+    return new JavaMethodBreakpointProperties();
+  }
+
+  @Override
+  public Breakpoint createJavaBreakpoint(Project project, XBreakpoint breakpoint) {
+    return new MethodBreakpoint(project, breakpoint);
+  }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaWildcardMethodBreakpointType.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaWildcardMethodBreakpointType.java
new file mode 100644
index 0000000..dd28ee2
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaWildcardMethodBreakpointType.java
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.ui.breakpoints;
+
+import com.intellij.debugger.DebuggerBundle;
+import com.intellij.debugger.HelpID;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.xdebugger.XDebuggerManager;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaMethodBreakpointProperties;
+
+import javax.swing.*;
+
+/**
+ * @author Egor
+ */
+public class JavaWildcardMethodBreakpointType extends JavaBreakpointTypeBase<JavaMethodBreakpointProperties> implements JavaBreakpointType {
+  public JavaWildcardMethodBreakpointType() {
+    super("java-wildcard-method", DebuggerBundle.message("method.breakpoints.tab.title"));
+  }
+
+  @NotNull
+  @Override
+  public Icon getEnabledIcon() {
+    return AllIcons.Debugger.Db_method_breakpoint;
+  }
+
+  @NotNull
+  @Override
+  public Icon getDisabledIcon() {
+    return AllIcons.Debugger.Db_disabled_method_breakpoint;
+  }
+
+  //@Override
+  protected String getHelpID() {
+    return HelpID.METHOD_BREAKPOINTS;
+  }
+
+  //@Override
+  public String getDisplayName() {
+    return DebuggerBundle.message("method.breakpoints.tab.title");
+  }
+
+  @Override
+  public String getDisplayText(XBreakpoint<JavaMethodBreakpointProperties> breakpoint) {
+    return JavaMethodBreakpointType.getText(breakpoint);
+  }
+
+  @Nullable
+  @Override
+  public XBreakpointCustomPropertiesPanel<XBreakpoint<JavaMethodBreakpointProperties>> createCustomPropertiesPanel() {
+    return new MethodBreakpointPropertiesPanel();
+  }
+
+  //@Override
+  //public Key<MethodBreakpoint> getBreakpointCategory() {
+  //  return MethodBreakpoint.CATEGORY;
+  //}
+
+  @Nullable
+  @Override
+  public JavaMethodBreakpointProperties createProperties() {
+    return new JavaMethodBreakpointProperties();
+  }
+
+  @Nullable
+  @Override
+  public XBreakpoint<JavaMethodBreakpointProperties> addBreakpoint(final Project project, JComponent parentComponent) {
+    final AddWildcardBreakpointDialog dialog = new AddWildcardBreakpointDialog(project);
+    dialog.show();
+    if (!dialog.isOK()) {
+      return null;
+    }
+    return ApplicationManager.getApplication().runWriteAction(new Computable<XBreakpoint<JavaMethodBreakpointProperties>>() {
+      @Override
+      public XBreakpoint<JavaMethodBreakpointProperties> compute() {
+        return XDebuggerManager.getInstance(project).getBreakpointManager().addBreakpoint(JavaWildcardMethodBreakpointType.this, new JavaMethodBreakpointProperties(
+          dialog.getClassPattern(),
+          dialog.getMethodName()));
+      }
+    });
+  }
+
+  @Override
+  public Breakpoint createJavaBreakpoint(Project project, XBreakpoint breakpoint) {
+    return new WildcardMethodBreakpoint(project, breakpoint);
+  }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java
index 307b962..2b32391 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java
@@ -54,6 +54,7 @@
 import com.intellij.util.StringBuilderSpinAllocator;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.xdebugger.XDebuggerUtil;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.sun.jdi.*;
 import com.sun.jdi.event.LocatableEvent;
 import com.sun.jdi.request.BreakpointRequest;
@@ -74,12 +75,8 @@
   private String myOwnerMethodName;
   public static final @NonNls Key<LineBreakpoint> CATEGORY = BreakpointCategory.lookup("line_breakpoints");
 
-  protected LineBreakpoint(Project project) {
-    super(project);
-  }
-
-  public LineBreakpoint(Project project, RangeHighlighter highlighter) {
-    super(project, highlighter);
+  protected LineBreakpoint(Project project, XBreakpoint xBreakpoint) {
+    super(project, xBreakpoint);
   }
 
   @Override
@@ -95,7 +92,7 @@
 
   @Override
   protected Icon getSetIcon(boolean isMuted) {
-    if (REMOVE_AFTER_HIT) {
+    if (isRemoveAfterHit()) {
       return isMuted ? AllIcons.Debugger.Db_muted_temporary_breakpoint : AllIcons.Debugger.Db_temporary_breakpoint;
     }
     return isMuted? AllIcons.Debugger.Db_muted_breakpoint : AllIcons.Debugger.Db_set_breakpoint;
@@ -108,7 +105,7 @@
 
   @Override
   protected Icon getVerifiedIcon(boolean isMuted) {
-    if (REMOVE_AFTER_HIT) {
+    if (isRemoveAfterHit()) {
       return isMuted ? AllIcons.Debugger.Db_muted_temporary_breakpoint : AllIcons.Debugger.Db_temporary_breakpoint;
     }
     return isMuted? AllIcons.Debugger.Db_muted_verified_breakpoint : AllIcons.Debugger.Db_verified_breakpoint;
@@ -349,9 +346,8 @@
   }
 
   private String getDisplayInfoInternal(boolean showPackageInfo, int totalTextLength) {
-    final RangeHighlighter highlighter = getHighlighter();
-    if(highlighter != null && highlighter.isValid() && isValid()) {
-      final int lineNumber = (highlighter.getDocument().getLineNumber(highlighter.getStartOffset()) + 1);
+    if(isValid()) {
+      final int lineNumber = getSourcePosition().getLine() + 1;
       String className = getClassName();
       final boolean hasClassInfo = className != null && className.length() > 0;
       final String methodName = getMethodName();
@@ -471,24 +467,19 @@
     return ContextUtil.getContextElement(getSourcePosition());
   }
 
-  public static LineBreakpoint create(@NotNull Project project, @NotNull Document document, int lineIndex) {
-    final RangeHighlighter highlighter = createHighlighter(project, document, lineIndex);
-    if (highlighter == null) {
-      return null;
-    }
-
-    LineBreakpoint breakpoint = new LineBreakpoint(project, highlighter);
+  public static LineBreakpoint create(@NotNull Project project, XBreakpoint xBreakpoint) {
+    LineBreakpoint breakpoint = new LineBreakpoint(project, xBreakpoint);
     return (LineBreakpoint)breakpoint.init();
   }
 
-  @Override
-  public boolean canMoveTo(SourcePosition position) {
-    if (!super.canMoveTo(position)) {
-      return false;
-    }
-    final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(position.getFile());
-    return canAddLineBreakpoint(myProject, document, position.getLine());
-  }
+  //@Override
+  //public boolean canMoveTo(SourcePosition position) {
+  //  if (!super.canMoveTo(position)) {
+  //    return false;
+  //  }
+  //  final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(position.getFile());
+  //  return canAddLineBreakpoint(myProject, document, position.getLine());
+  //}
 
   public static boolean canAddLineBreakpoint(Project project, final Document document, final int lineIndex) {
     if (lineIndex < 0 || lineIndex >= document.getLineCount()) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpointFactory.java
deleted file mode 100644
index 0042074..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpointFactory.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.ui.breakpoints;
-
-import com.intellij.debugger.DebuggerBundle;
-import com.intellij.debugger.HelpID;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import org.jdom.Element;
-
-import javax.swing.*;
-
-/**
- * @author Eugene Zhuravlev
- *         Date: Apr 26, 2005
- */
-public class LineBreakpointFactory extends BreakpointFactory {
-  @Override
-  public Breakpoint createBreakpoint(Project project, final Element element) {
-    return new LineBreakpoint(project);
-  }
-
-  @Override
-  public Icon getIcon() {
-    return AllIcons.Debugger.Db_set_breakpoint;
-  }
-
-  @Override
-  public Icon getDisabledIcon() {
-    return AllIcons.Debugger.Db_disabled_breakpoint;
-  }
-
-  @Override
-  protected String getHelpID() {
-    return HelpID.LINE_BREAKPOINTS;
-  }
-
-  @Override
-  public String getDisplayName() {
-    return DebuggerBundle.message("line.breakpoints.tab.title");
-  }
-
-  @Override
-  public BreakpointPropertiesPanel createBreakpointPropertiesPanel(Project project, boolean compact) {
-    return new LineBreakpointPropertiesPanel(project, compact);
-  }
-
-  @Override
-  public Key<LineBreakpoint> getBreakpointCategory() {
-    return LineBreakpoint.CATEGORY;
-  }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java
index 90a839d..be10d56 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java
@@ -38,10 +38,13 @@
 import com.intellij.openapi.project.IndexNotReadyException;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.JDOMExternalizerUtil;
 import com.intellij.openapi.util.Key;
 import com.intellij.psi.*;
 import com.intellij.util.StringBuilderSpinAllocator;
 import com.intellij.util.text.CharArrayUtil;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.sun.jdi.AbsentInformationException;
 import com.sun.jdi.Location;
 import com.sun.jdi.Method;
@@ -52,31 +55,29 @@
 import com.sun.jdi.request.EventRequest;
 import com.sun.jdi.request.MethodEntryRequest;
 import com.sun.jdi.request.MethodExitRequest;
+import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaMethodBreakpointProperties;
 
 import javax.swing.*;
 import java.util.Iterator;
 import java.util.Set;
 
-public class MethodBreakpoint extends BreakpointWithHighlighter {
+public class MethodBreakpoint extends BreakpointWithHighlighter<JavaMethodBreakpointProperties> {
   private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.breakpoints.MethodBreakpoint");
-  public boolean WATCH_ENTRY = true;
-  public boolean WATCH_EXIT  = true;
-
-  @Nullable private String myMethodName;
   @Nullable private JVMName mySignature;
   private boolean myIsStatic;
 
   public static final @NonNls Key<MethodBreakpoint> CATEGORY = BreakpointCategory.lookup("method_breakpoints");
 
-  protected MethodBreakpoint(@NotNull Project project) {
-    super(project);
+  protected MethodBreakpoint(@NotNull Project project, XBreakpoint breakpoint) {
+    super(project, breakpoint);
   }
 
   private MethodBreakpoint(@NotNull Project project, @NotNull RangeHighlighter highlighter) {
-    super(project, highlighter);
+    super(project, highlighter, null);
   }
 
   public boolean isStatic() {
@@ -104,21 +105,25 @@
   }
 
   public boolean isValid() {
-    return super.isValid() && myMethodName != null;
+    return super.isValid() && getMethodName() != null;
   }
 
   protected void reload(@NotNull PsiFile psiFile) {
-    myMethodName = null;
+    setMethodName(null);
     mySignature = null;
 
     MethodDescriptor descriptor = getMethodDescriptor(myProject, psiFile, getSourcePosition());
     if (descriptor != null) {
-      myMethodName = descriptor.methodName;
+      setMethodName(descriptor.methodName);
       mySignature = descriptor.methodSignature;
       myIsStatic = descriptor.isStatic;
     }
+    PsiClass psiClass = getPsiClass();
+    if (psiClass != null) {
+      getProperties().myClassPattern = psiClass.getQualifiedName();
+    }
     if (myIsStatic) {
-      INSTANCE_FILTERS_ENABLED = false;
+      setInstanceFiltersEnabled(false);
     }
   }
 
@@ -130,7 +135,7 @@
         String signature = method.signature();
         String name = method.name();
 
-        if (myMethodName.equals(name) && mySignature.getName(debugProcess).equals(signature)) {
+        if (getMethodName().equals(name) && mySignature.getName(debugProcess).equals(signature)) {
           hasMethod = true;
           break;
         }
@@ -144,7 +149,7 @@
       }
 
       RequestManagerImpl requestManager = debugProcess.getRequestsManager();
-      if (WATCH_ENTRY) {
+      if (isWatchEntry()) {
         MethodEntryRequest entryRequest = (MethodEntryRequest)findRequest(debugProcess, MethodEntryRequest.class);
         if (entryRequest == null) {
           entryRequest = requestManager.createMethodEntryRequest(this);
@@ -157,7 +162,7 @@
         entryRequest.addClassFilter(classType);
         debugProcess.getRequestsManager().enableRequest(entryRequest);
       }
-      if (WATCH_EXIT) {
+      if (isWatchExit()) {
         MethodExitRequest exitRequest = (MethodExitRequest)findRequest(debugProcess, MethodExitRequest.class);
         if (exitRequest == null) {
           exitRequest = requestManager.createMethodExitRequest(this);
@@ -256,11 +261,11 @@
         if (classNameExists) {
           buffer.append(className);
         }
-        if(myMethodName != null) {
+        if(getMethodName() != null) {
           if (classNameExists) {
             buffer.append(".");
           }
-          buffer.append(myMethodName);
+          buffer.append(getMethodName());
         }
       }
       else {
@@ -281,16 +286,16 @@
   }
 
   public boolean matchesEvent(@NotNull final LocatableEvent event, final DebugProcessImpl process) throws EvaluateException {
-    if (myMethodName == null || mySignature == null) {
+    if (getMethodName() == null || mySignature == null) {
       return false;
     }
     final Method method = event.location().method();
-    return method != null && method.name().equals(myMethodName) && method.signature().equals(mySignature.getName(process));
+    return method != null && method.name().equals(getMethodName()) && method.signature().equals(mySignature.getName(process));
   }
 
   @Nullable
-  public static MethodBreakpoint create(@NotNull Project project, @NotNull Document document, int lineIndex) {
-    final MethodBreakpoint breakpoint = new MethodBreakpoint(project, createHighlighter(project, document, lineIndex));
+  public static MethodBreakpoint create(@NotNull Project project, XBreakpoint xBreakpoint) {
+    final MethodBreakpoint breakpoint = new MethodBreakpoint(project, xBreakpoint);
     return (MethodBreakpoint)breakpoint.init();
   }
 
@@ -362,6 +367,19 @@
     return null;
   }
 
+  @Override
+  public void readExternal(@NotNull Element breakpointNode) throws InvalidDataException {
+    super.readExternal(breakpointNode);
+    try {
+      getProperties().WATCH_ENTRY = Boolean.valueOf(JDOMExternalizerUtil.readField(breakpointNode, "WATCH_ENTRY"));
+    } catch (Exception e) {
+    }
+    try {
+      getProperties().WATCH_EXIT = Boolean.valueOf(JDOMExternalizerUtil.readField(breakpointNode, "WATCH_EXIT"));
+    } catch (Exception e) {
+    }
+  }
+
   public String toString() {
     return getDescription();
   }
@@ -376,6 +394,23 @@
     return false;
   }
 
+  private boolean isWatchEntry() {
+    return getProperties().WATCH_ENTRY;
+  }
+
+  private boolean isWatchExit() {
+    return getProperties().WATCH_EXIT;
+  }
+
+  @Nullable
+  private String getMethodName() {
+    return getProperties().myMethodName;
+  }
+
+  private void setMethodName(@Nullable String methodName) {
+    getProperties().myMethodName = methodName;
+  }
+
   private static final class MethodDescriptor {
     String methodName;
     JVMName methodSignature;
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java
deleted file mode 100644
index a08e2a1..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.debugger.ui.breakpoints;
-
-import com.intellij.debugger.DebuggerBundle;
-import com.intellij.debugger.DebuggerManagerEx;
-import com.intellij.debugger.HelpID;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import org.jdom.Element;
-
-import javax.swing.*;
-
-/**
- * @author Eugene Zhuravlev
- *         Date: Apr 26, 2005
- */
-public class MethodBreakpointFactory extends BreakpointFactory{
-  @Override
-  public Breakpoint createBreakpoint(Project project, final Element element) {
-    return element.getAttributeValue(WildcardMethodBreakpoint.JDOM_LABEL) != null? new WildcardMethodBreakpoint(project) : new MethodBreakpoint(project);
-  }
-
-  @Override
-  public Icon getIcon() {
-    return AllIcons.Debugger.Db_method_breakpoint;
-  }
-
-  @Override
-  public Icon getDisabledIcon() {
-    return AllIcons.Debugger.Db_disabled_method_breakpoint;
-  }
-
-  @Override
-  protected String getHelpID() {
-    return HelpID.METHOD_BREAKPOINTS;
-  }
-
-  @Override
-  public String getDisplayName() {
-    return DebuggerBundle.message("method.breakpoints.tab.title");
-  }
-
-  @Override
-  public BreakpointPropertiesPanel createBreakpointPropertiesPanel(Project project, boolean compact) {
-    return new MethodBreakpointPropertiesPanel(project, compact);
-  }
-
-  @Override
-  public Key<MethodBreakpoint> getBreakpointCategory() {
-    return MethodBreakpoint.CATEGORY;
-  }
-
-  @Override
-  public boolean canAddBreakpoints() {
-    return true;
-  }
-
-  @Override
-  public WildcardMethodBreakpoint addBreakpoint(Project project) {
-    AddWildcardBreakpointDialog dialog = new AddWildcardBreakpointDialog(project);
-    dialog.show();
-    WildcardMethodBreakpoint methodBreakpoint;
-    methodBreakpoint = !dialog.isOK()
-                       ? null
-                       : DebuggerManagerEx.getInstanceEx(project).getBreakpointManager()
-                         .addMethodBreakpoint(dialog.getClassPattern(), dialog.getMethodName());
-    return methodBreakpoint;
-  }
-}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointPropertiesPanel.java
index c50b699..bf74192 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointPropertiesPanel.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointPropertiesPanel.java
@@ -21,24 +21,30 @@
 package com.intellij.debugger.ui.breakpoints;
 
 import com.intellij.debugger.DebuggerBundle;
-import com.intellij.openapi.project.Project;
 import com.intellij.ui.IdeBorderFactory;
 import com.intellij.util.ui.DialogUtil;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaMethodBreakpointProperties;
 
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 
-public class MethodBreakpointPropertiesPanel extends BreakpointPropertiesPanel {
+public class MethodBreakpointPropertiesPanel extends XBreakpointCustomPropertiesPanel<XBreakpoint<JavaMethodBreakpointProperties>> {
   private JCheckBox myWatchEntryCheckBox;
   private JCheckBox myWatchExitCheckBox;
 
-  public MethodBreakpointPropertiesPanel(final Project project, boolean compact) {
-    super(project, MethodBreakpoint.CATEGORY, compact);
-  }
+  //public MethodBreakpointPropertiesPanel(final Project project, boolean compact) {
+  //  super(project, MethodBreakpoint.CATEGORY, compact);
+  //}
 
-  protected JComponent createSpecialBox() {
+
+  @NotNull
+  @Override
+  public JComponent getComponent() {
     JPanel _panel, _panel0;
 
     myWatchEntryCheckBox = new JCheckBox(DebuggerBundle.message("label.method.breakpoint.properties.panel.method.entry"));
@@ -86,31 +92,15 @@
     return _panel;
   }
 
-  public void initFrom(Breakpoint breakpoint, boolean moreOptionsVisible) {
-    super.initFrom(breakpoint, moreOptionsVisible);
-    if (breakpoint instanceof MethodBreakpoint) {
-      MethodBreakpoint methodBreakpoint = (MethodBreakpoint)breakpoint;
-      myWatchEntryCheckBox.setSelected(methodBreakpoint.WATCH_ENTRY);
-      myWatchExitCheckBox.setSelected(methodBreakpoint.WATCH_EXIT);
-    }
-    else if (breakpoint instanceof WildcardMethodBreakpoint){
-      final WildcardMethodBreakpoint methodBreakpoint = ((WildcardMethodBreakpoint)breakpoint);
-      myWatchEntryCheckBox.setSelected(methodBreakpoint.WATCH_ENTRY);
-      myWatchExitCheckBox.setSelected(methodBreakpoint.WATCH_EXIT);
-    }
+  @Override
+  public void loadFrom(@NotNull XBreakpoint<JavaMethodBreakpointProperties> breakpoint) {
+    myWatchEntryCheckBox.setSelected(breakpoint.getProperties().WATCH_ENTRY);
+    myWatchExitCheckBox.setSelected(breakpoint.getProperties().WATCH_EXIT);
   }
 
-  public void saveTo(Breakpoint breakpoint) {
-    if (breakpoint instanceof MethodBreakpoint) {
-      MethodBreakpoint methodBreakpoint = (MethodBreakpoint)breakpoint;
-      methodBreakpoint.WATCH_ENTRY = myWatchEntryCheckBox.isSelected();
-      methodBreakpoint.WATCH_EXIT = myWatchExitCheckBox.isSelected();
-    }
-    else if (breakpoint instanceof WildcardMethodBreakpoint){
-      final WildcardMethodBreakpoint methodBreakpoint = ((WildcardMethodBreakpoint)breakpoint);
-      methodBreakpoint.WATCH_ENTRY = myWatchEntryCheckBox.isSelected();
-      methodBreakpoint.WATCH_EXIT = myWatchExitCheckBox.isSelected();
-    }
-    super.saveTo(breakpoint);
+  @Override
+  public void saveTo(@NotNull XBreakpoint<JavaMethodBreakpointProperties> breakpoint) {
+    breakpoint.getProperties().WATCH_ENTRY = myWatchEntryCheckBox.isSelected();
+    breakpoint.getProperties().WATCH_EXIT = myWatchExitCheckBox.isSelected();
   }
 }
\ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java
index 82f617a..19a187d 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java
@@ -18,10 +18,11 @@
 import com.intellij.debugger.SourcePosition;
 import com.intellij.debugger.engine.DebugProcessImpl;
 import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -31,18 +32,11 @@
  */
 public class RunToCursorBreakpoint extends LineBreakpoint {
   private final boolean myRestoreBreakpoints;
-  @Nullable
   private final SourcePosition myCustomPosition;
-
-  protected RunToCursorBreakpoint(@NotNull Project project, @NotNull RangeHighlighter highlighter, boolean restoreBreakpoints) {
-    super(project, highlighter);
-    setVisible(false);
-    myRestoreBreakpoints = restoreBreakpoints;
-    myCustomPosition = null;
-  }
+  private String mySuspendPolicy;
 
   protected RunToCursorBreakpoint(@NotNull Project project, @NotNull SourcePosition pos, boolean restoreBreakpoints) {
-    super(project);
+    super(project, null);
     myCustomPosition = pos;
     setVisible(false);
     myRestoreBreakpoints = restoreBreakpoints;
@@ -50,7 +44,51 @@
 
   @Override
   public SourcePosition getSourcePosition() {
-    return myCustomPosition != null ? myCustomPosition : super.getSourcePosition();
+    return myCustomPosition;
+  }
+
+  @Override
+  public void reload() {
+  }
+
+  @Override
+  public String getSuspendPolicy() {
+    return mySuspendPolicy;
+  }
+
+  public void setSuspendPolicy(String policy) {
+    mySuspendPolicy = policy;
+  }
+
+  protected boolean isLogEnabled() {
+    return false;
+  }
+
+  @Override
+  protected boolean isLogExpressionEnabled() {
+    return false;
+  }
+
+  @Override
+  public boolean isEnabled() {
+    return true;
+  }
+
+  public boolean isCountFilterEnabled() {
+    return false;
+  }
+
+  public boolean isClassFiltersEnabled() {
+    return false;
+  }
+
+  public boolean isInstanceFiltersEnabled() {
+    return false;
+  }
+
+  @Override
+  protected boolean isConditionEnabled() {
+    return false;
   }
 
   public boolean isRestoreBreakpoints() {
@@ -63,6 +101,11 @@
   }
 
   @Override
+  public boolean isValid() {
+    return true;
+  }
+
+  @Override
   protected boolean isMuted(@NotNull final DebugProcessImpl debugProcess) {
     return false;  // always enabled
   }
@@ -74,17 +117,9 @@
       return null;
     }
 
-    final RangeHighlighter highlighter = createHighlighter(project, document, lineIndex);
-    if (highlighter == null) {
-      return null;
-    }
+    PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
+    SourcePosition pos = SourcePosition.createFromLine(psiFile, lineIndex);
 
-    final RunToCursorBreakpoint breakpoint = new RunToCursorBreakpoint(project, highlighter, restoreBreakpoints);
-    final RangeHighlighter h = breakpoint.getHighlighter();
-    if (h != null) {
-      h.dispose();
-    }
-
-    return (RunToCursorBreakpoint)breakpoint.init();
+    return new RunToCursorBreakpoint(project, pos, restoreBreakpoints);
   }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StepIntoBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StepIntoBreakpoint.java
index 6e39e5a..af7d675 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StepIntoBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/StepIntoBreakpoint.java
@@ -153,7 +153,7 @@
     if (pos != null) {
       final StepIntoBreakpoint breakpoint = new StepIntoBreakpoint(project, pos, filter);
       breakpoint.init();
-      breakpoint.LOG_ENABLED = false;
+      breakpoint.setLogEnabled(false);
       return breakpoint;
     }
     return null;
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java
index f6c0dc3..295fddb 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java
@@ -23,15 +23,20 @@
 import com.intellij.debugger.engine.evaluation.EvaluateException;
 import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
 import com.intellij.debugger.engine.requests.RequestManagerImpl;
+import com.intellij.debugger.impl.DebuggerUtilsEx;
 import com.intellij.icons.AllIcons;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.JDOMExternalizerUtil;
 import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.WriteExternalException;
 import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.util.StringBuilderSpinAllocator;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.sun.jdi.AbsentInformationException;
 import com.sun.jdi.Location;
 import com.sun.jdi.Method;
@@ -45,37 +50,33 @@
 import org.jdom.Element;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaMethodBreakpointProperties;
 
 import javax.swing.*;
 import java.util.Iterator;
 import java.util.Set;
 
-public class WildcardMethodBreakpoint extends Breakpoint {
+public class WildcardMethodBreakpoint extends Breakpoint<JavaMethodBreakpointProperties> {
   private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.breakpoints.ExceptionBreakpoint");
 
-  public boolean WATCH_ENTRY = true;
-  public boolean WATCH_EXIT  = true;
-  private String myClassPattern;
-  private String myMethodName;
-
   public static final String JDOM_LABEL = "wildcard_breakpoint";
 
-  public WildcardMethodBreakpoint(Project project) {
-    super(project);
+  public WildcardMethodBreakpoint(Project project, XBreakpoint breakpoint) {
+    super(project, breakpoint);
   }
 
   public Key<MethodBreakpoint> getCategory() {
     return MethodBreakpoint.CATEGORY;
   }
 
-  protected WildcardMethodBreakpoint(Project project, @NotNull String classPattern, @NotNull String methodName) {
-    super(project);
-    myClassPattern = classPattern;
-    myMethodName = methodName;
+  protected WildcardMethodBreakpoint(Project project, @NotNull String classPattern, @NotNull String methodName, XBreakpoint breakpoint) {
+    super(project, breakpoint);
+    setClassPattern(classPattern);
+    setMethodName(methodName);
   }
 
   public String getClassName() {
-    return myClassPattern;
+    return getClassPattern();
   }
 
   public @Nullable String getShortClassName() {
@@ -83,11 +84,15 @@
   }
 
   public String getMethodName() {
-    return myMethodName;
+    return getProperties().myMethodName;
   }
 
   public PsiClass getPsiClass() {
-    return null;
+    return PsiDocumentManager.getInstance(myProject).commitAndRunReadAction(new Computable<PsiClass>() {
+      public PsiClass compute() {
+        return getClassName() != null ? DebuggerUtilsEx.findClass(getClassName(), myProject, GlobalSearchScope.allScope(myProject)) : null;
+      }
+    });
   }
 
   public String getDisplayName() {
@@ -96,9 +101,9 @@
     }
     final StringBuilder buffer = StringBuilderSpinAllocator.alloc();
     try {
-      buffer.append(myClassPattern);
+      buffer.append(getClassPattern());
       buffer.append(".");
-      buffer.append(myMethodName);
+      buffer.append(getMethodName());
       buffer.append("()");
       return buffer.toString();
     }
@@ -108,7 +113,7 @@
   }
 
   public Icon getIcon() {
-    if (!ENABLED) {
+    if (!isEnabled()) {
       final Breakpoint master = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().findMasterBreakpoint(this);
       return master == null? AllIcons.Debugger.Db_disabled_method_breakpoint : AllIcons.Debugger.Db_dep_method_breakpoint;
     }
@@ -124,12 +129,12 @@
 
   public void createRequest(DebugProcessImpl debugProcess) {
     DebuggerManagerThreadImpl.assertIsManagerThread();
-    if (!ENABLED || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+    if (!isEnabled() || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
       return;
     }
     try {
       RequestManagerImpl requestManager = debugProcess.getRequestsManager();
-      if (WATCH_ENTRY) {
+      if (isWatchEntry()) {
         MethodEntryRequest entryRequest = (MethodEntryRequest)findRequest(debugProcess, MethodEntryRequest.class);
         if (entryRequest == null) {
           entryRequest = requestManager.createMethodEntryRequest(this);
@@ -137,10 +142,10 @@
         else {
           entryRequest.disable();
         }
-        entryRequest.addClassFilter(myClassPattern);
+        entryRequest.addClassFilter(getClassPattern());
         debugProcess.getRequestsManager().enableRequest(entryRequest);
       }
-      if (WATCH_EXIT) {
+      if (isWatchExit()) {
         MethodExitRequest exitRequest = (MethodExitRequest)findRequest(debugProcess, MethodExitRequest.class);
         if (exitRequest == null) {
           exitRequest = requestManager.createMethodExitRequest(this);
@@ -148,7 +153,7 @@
         else {
           exitRequest.disable();
         }
-        exitRequest.addClassFilter(myClassPattern);
+        exitRequest.addClassFilter(getClassPattern());
         debugProcess.getRequestsManager().enableRequest(exitRequest);
       }
     }
@@ -212,19 +217,19 @@
   }
 
   public boolean isValid() {
-    return myClassPattern != null && myMethodName != null;
+    return getClassPattern() != null && getMethodName() != null;
   }
 
-  @SuppressWarnings({"HardCodedStringLiteral"}) public void writeExternal(Element parentNode) throws WriteExternalException {
-    super.writeExternal(parentNode);
-    parentNode.setAttribute(JDOM_LABEL, "true");
-    if (myClassPattern != null) {
-      parentNode.setAttribute("class_name", myClassPattern);
-    }
-    if (myMethodName != null) {
-      parentNode.setAttribute("method_name", myMethodName);
-    }
-  }
+  //@SuppressWarnings({"HardCodedStringLiteral"}) public void writeExternal(Element parentNode) throws WriteExternalException {
+  //  super.writeExternal(parentNode);
+  //  parentNode.setAttribute(JDOM_LABEL, "true");
+  //  if (getClassPattern() != null) {
+  //    parentNode.setAttribute("class_name", getClassPattern());
+  //  }
+  //  if (getMethodName() != null) {
+  //    parentNode.setAttribute("method_name", getMethodName());
+  //  }
+  //}
 
   public PsiElement getEvaluationElement() {
     return null;
@@ -235,11 +240,20 @@
 
     //noinspection HardCodedStringLiteral
     String className = parentNode.getAttributeValue("class_name");
-    myClassPattern = className;
+    setClassPattern(className);
 
     //noinspection HardCodedStringLiteral
     String methodName = parentNode.getAttributeValue("method_name");
-    myMethodName = methodName;
+    setMethodName(methodName);
+
+    try {
+      getProperties().WATCH_ENTRY = Boolean.valueOf(JDOMExternalizerUtil.readField(parentNode, "WATCH_ENTRY"));
+    } catch (Exception e) {
+    }
+    try {
+      getProperties().WATCH_EXIT = Boolean.valueOf(JDOMExternalizerUtil.readField(parentNode, "WATCH_EXIT"));
+    } catch (Exception e) {
+    }
 
     if(className == null || methodName == null) {
       throw new InvalidDataException();
@@ -248,10 +262,38 @@
 
   public boolean matchesEvent(final LocatableEvent event){
     final Method method = event.location().method();
-    return method != null && myMethodName.equals(method.name());
+    return method != null && getMethodName().equals(method.name());
   }
 
-  public static WildcardMethodBreakpoint create(Project project, final String classPattern, final String methodName) {
-    return new WildcardMethodBreakpoint(project, classPattern, methodName);
+  public static WildcardMethodBreakpoint create(Project project, final String classPattern, final String methodName, XBreakpoint xBreakpoint) {
+    return new WildcardMethodBreakpoint(project, classPattern, methodName, xBreakpoint);
+  }
+
+  private boolean isWatchEntry() {
+    return getProperties().WATCH_ENTRY;
+  }
+
+  private void setWatchEntry(boolean WATCH_ENTRY) {
+    getProperties().WATCH_ENTRY = WATCH_ENTRY;
+  }
+
+  private boolean isWatchExit() {
+    return getProperties().WATCH_EXIT;
+  }
+
+  private void setWatchExit(boolean WATCH_EXIT) {
+    getProperties().WATCH_EXIT = WATCH_EXIT;
+  }
+
+  private String getClassPattern() {
+    return getProperties().myClassPattern;
+  }
+
+  private void setClassPattern(String classPattern) {
+    getProperties().myClassPattern = classPattern;
+  }
+
+  private void setMethodName(String methodName) {
+    getProperties().myMethodName = methodName;
   }
 }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreePanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreePanel.java
index 25cc972..c04f1bf 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreePanel.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreePanel.java
@@ -93,7 +93,7 @@
             getTree().rebuild(context);
           }
         }
-        catch (VMDisconnectedException e) {
+        catch (VMDisconnectedException ignored) {
           // ignored
         }
       }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java
index 30306a4..788cb17 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java
@@ -83,11 +83,13 @@
     }
   }
 
+  @Override
   protected void build(DebuggerContextImpl context) {
     myAnyNewLocals = false;
     buildWhenPaused(context, new RefreshFrameTreeCommand(context));
   }
 
+  @Override
   public void restoreNodeState(DebuggerTreeNodeImpl node) {
     if (myAnyNewLocals) {
       final NodeDescriptorImpl descriptor = node.getDescriptor();
@@ -107,6 +109,7 @@
   }
 
 
+  @Override
   protected DebuggerCommandImpl getBuildNodeCommand(final DebuggerTreeNodeImpl node) {
     if (node.getDescriptor() instanceof StackFrameDescriptorImpl) {
       return new BuildFrameTreeVariablesCommand(node);
@@ -119,6 +122,7 @@
       super(stackNode);
     }
     
+    @Override
     protected void buildVariables(final StackFrameDescriptorImpl stackDescriptor, final EvaluationContextImpl evaluationContext) throws EvaluateException {
       final DebuggerContextImpl debuggerContext = getDebuggerContext();
       final SourcePosition sourcePosition = debuggerContext.getSourcePosition();
@@ -135,6 +139,7 @@
           final EvaluationContextImpl evalContext = debuggerContext.createEvaluationContext();
           final Pair<Set<String>, Set<TextWithImports>> usedVars =
             ApplicationManager.getApplication().runReadAction(new Computable<Pair<Set<String>, Set<TextWithImports>>>() {
+              @Override
               public Pair<Set<String>, Set<TextWithImports>> compute() {
                 return findReferencedVars(visibleVariables.keySet(), sourcePosition, evalContext);
               }
@@ -396,6 +401,7 @@
       super(context);
     }
 
+    @Override
     public void contextAction() throws Exception {
       DebuggerTreeNodeImpl rootNode;
 
@@ -433,7 +439,7 @@
               rootNode.add(MessageDescriptor.THREAD_IS_RUNNING);
             }
           }
-          catch (ObjectCollectedException e) {
+          catch (ObjectCollectedException ignored) {
             rootNode.add(new MessageDescriptor(DebuggerBundle.message("label.thread.node.thread.collected", currentThread.name())));
           }
         }
@@ -448,12 +454,14 @@
 
       final DebuggerTreeNodeImpl rootNode1 = rootNode;
       DebuggerInvocationUtil.swingInvokeLater(getProject(), new Runnable() {
+        @Override
         public void run() {
           getMutableModel().setRoot(rootNode1);
           treeChanged();
 
           final TreeModel model = getModel();
           model.addTreeModelListener(new TreeModelAdapter() {
+            @Override
             public void treeStructureChanged(TreeModelEvent e) {
               final Object[] path = e.getPath();
               if (path.length > 0 && path[path.length - 1] == rootNode1) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FramesList.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FramesList.java
index 9967b70..d0d25f1 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FramesList.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FramesList.java
@@ -35,15 +35,18 @@
     doInit();
   }
 
+  @Override
   protected FramesListRenderer createListRenderer() {
     return new FramesListRenderer();
   }
 
+  @Override
   protected void onFrameChanged(final Object selectedValue) {
     final StackFrameDescriptorImpl descriptor = selectedValue instanceof StackFrameDescriptorImpl? (StackFrameDescriptorImpl)selectedValue : null;
     final Method newMethod = descriptor != null? descriptor.getMethod() : null;
     if (!Comparing.equal(mySelectedMethod, newMethod)) {
       SwingUtilities.invokeLater(new Runnable() {
+        @Override
         public void run() {
           repaint();
         }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FramesListRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FramesListRenderer.java
index c6e6228..c3368cd 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FramesListRenderer.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FramesListRenderer.java
@@ -16,14 +16,14 @@
 package com.intellij.debugger.ui.impl;
 
 import com.intellij.debugger.ui.impl.watch.StackFrameDescriptorImpl;
-import com.intellij.ui.JBColor;
-import com.intellij.xdebugger.impl.ui.tree.ValueMarkup;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.ui.ColoredListCellRenderer;
+import com.intellij.ui.JBColor;
 import com.intellij.ui.SimpleTextAttributes;
 import com.intellij.util.ui.UIUtil;
+import com.intellij.xdebugger.impl.ui.tree.ValueMarkup;
 import com.intellij.xdebugger.ui.DebuggerColors;
 import com.sun.jdi.Method;
 
@@ -38,6 +38,7 @@
     myColorScheme = EditorColorsManager.getInstance().getGlobalScheme();
   }
 
+  @Override
   protected void customizeCellRenderer(final JList list, final Object item, final int index, final boolean selected, final boolean hasFocus) {
     if (!(item instanceof StackFrameDescriptorImpl)) {
       append(item.toString(), SimpleTextAttributes.GRAYED_ATTRIBUTES);
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java
index 4b3f145..e059e78 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java
@@ -59,10 +59,12 @@
     setLvalue(!field.isFinal());
   }
 
+  @Override
   public Field getField() {
     return myField;
   }
 
+  @Override
   public ObjectReference getObject() {
     return myObject;
   }
@@ -131,6 +133,7 @@
     }
   }
 
+  @Override
   public void setAncestor(NodeDescriptor oldDescriptor) {
     super.setAncestor(oldDescriptor);
     final Boolean isPrimitive = ((FieldDescriptorImpl)oldDescriptor).myIsPrimitive;
@@ -141,6 +144,7 @@
   }
 
 
+  @Override
   public boolean isPrimitive() {
     if (myIsPrimitive == null) {
       final Value value = getValue();
@@ -154,12 +158,13 @@
     return myIsPrimitive.booleanValue();
   }
 
+  @Override
   public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException {
     DebuggerManagerThreadImpl.assertIsManagerThread();
     try {
       return (myObject != null) ? myObject.getValue(myField) : myField.declaringType().getValue(myField);
     }
-    catch (ObjectCollectedException e) {
+    catch (ObjectCollectedException ignored) {
       throw EvaluateExceptionUtil.OBJECT_WAS_COLLECTED;
     }
   }
@@ -168,6 +173,7 @@
     return myIsStatic;
   }
 
+  @Override
   public String getName() {
     final String fieldName = myField.name();
     if (isOuterLocalVariableValue() && NodeRendererSettings.getInstance().getClassRenderer().SHOW_VAL_FIELDS_AS_LOCAL_VARIABLES) {
@@ -180,11 +186,12 @@
     try {
       return DebuggerUtils.isSynthetic(myField) && myField.name().startsWith(OUTER_LOCAL_VAR_FIELD_PREFIX);
     }
-    catch (UnsupportedOperationException e) {
+    catch (UnsupportedOperationException ignored) {
       return false;
     }
   }
 
+  @Override
   public String calcValueName() {
     final ClassRenderer classRenderer = NodeRendererSettings.getInstance().getClassRenderer();
     StringBuilder buf = StringBuilderSpinAllocator.alloc();
@@ -201,6 +208,7 @@
     }
   }
 
+  @Override
   public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException {
     PsiElementFactory elementFactory = JavaPsiFacade.getInstance(context.getProject()).getElementFactory();
     String fieldName;
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/MessageDescriptor.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/MessageDescriptor.java
index 026f2ad..6f2aa4e 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/MessageDescriptor.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/MessageDescriptor.java
@@ -59,17 +59,21 @@
     return myKind;
   }
 
+  @Override
   public String getLabel() {
     return myMessage;
   }
 
+  @Override
   public boolean isExpandable() {
     return false;
   }
 
+  @Override
   public void setContext(EvaluationContextImpl context) {
   }
 
+  @Override
   protected String calcRepresentation(EvaluationContextImpl context, DescriptorLabelListener labelListener) throws EvaluateException {
     DebuggerManagerThreadImpl.assertIsManagerThread();
     return myMessage;
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java
index a009733..f2f5b1c 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java
@@ -52,15 +52,21 @@
   private final List<NodeDescriptorImpl> myChildren = new ArrayList<NodeDescriptorImpl>();
   private static final Key<Map<ObjectReference, ValueMarkup>> MARKUP_MAP_KEY = new Key<Map<ObjectReference, ValueMarkup>>("ValueMarkupMap");
 
+  @Override
   public String getName() {
     return null;
   }
 
+  @Override
   public <T> T getUserData(Key<T> key) {
-    if(myUserData == null) return null;
-    return (T) myUserData.get(key);
+    if (myUserData == null) {
+      return null;
+    }
+    //noinspection unchecked
+    return (T)myUserData.get(key);
   }
 
+  @Override
   public <T> void putUserData(Key<T> key, T value) {
     if(myUserData == null) {
       myUserData = new HashMap<Key, Object>();
@@ -91,12 +97,12 @@
 
   protected abstract String calcRepresentation(EvaluationContextImpl context, DescriptorLabelListener labelListener) throws EvaluateException;
 
-  private EvaluateException processException(Exception e) {
-    if(e instanceof InconsistentDebugInfoException) {
+  private static EvaluateException processException(Exception e) {
+    if (e instanceof InconsistentDebugInfoException) {
       return new EvaluateException(DebuggerBundle.message("error.inconsistent.debug.info"), null);
     }
 
-    else if(e instanceof InvalidStackFrameException) {
+    else if (e instanceof InvalidStackFrameException) {
       return new EvaluateException(DebuggerBundle.message("error.invalid.stackframe"), null);
     }
     else {
@@ -104,6 +110,7 @@
     }
   }
 
+  @Override
   public void displayAs(NodeDescriptor descriptor) {
     if (descriptor instanceof NodeDescriptorImpl) {
       final NodeDescriptorImpl that = (NodeDescriptorImpl)descriptor;
@@ -122,6 +129,7 @@
     return myEvaluateException;
   }
 
+  @Override
   public String getLabel() {
     return myLabel;
   }
@@ -149,6 +157,7 @@
     return myChildren;
   }
 
+  @Override
   public void setAncestor(NodeDescriptor oldDescriptor) {
     displayAs(oldDescriptor);
   }
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/StackFrameDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/StackFrameDescriptorImpl.java
index 41a5384..8e11e54 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/StackFrameDescriptorImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/StackFrameDescriptorImpl.java
@@ -34,6 +34,8 @@
 import com.intellij.psi.PsiFile;
 import com.intellij.ui.FileColorManager;
 import com.intellij.util.StringBuilderSpinAllocator;
+import com.intellij.util.ui.TextTransferable;
+import com.intellij.xdebugger.frame.XStackFrame;
 import com.intellij.xdebugger.impl.ui.tree.ValueMarkup;
 import com.sun.jdi.*;
 import org.jetbrains.annotations.Nullable;
@@ -50,6 +52,7 @@
   private int myUiIndex;
   private String myName = null;
   private Location myLocation;
+  private final XStackFrame myXStackFrame;
   private MethodsTracker.MethodOccurrence myMethodOccurrence;
   private boolean myIsSynthetic;
   private boolean myIsInLibraryContent;
@@ -67,6 +70,7 @@
       myMethodOccurrence = tracker.getMethodOccurrence(myLocation.method());
       myIsSynthetic = DebuggerUtils.isSynthetic(myMethodOccurrence.getMethod());
       ApplicationManager.getApplication().runReadAction(new Runnable() {
+        @Override
         public void run() {
           final SourcePosition position = ContextUtil.getSourcePosition(StackFrameDescriptorImpl.this);
           final PsiFile file = position != null? position.getFile() : null;
@@ -83,7 +87,7 @@
         }
       });
     }
-    catch(InternalException e) {
+    catch (InternalException e) {
       LOG.info(e);
       myLocation = null;
       myMethodOccurrence = tracker.getMethodOccurrence(null);
@@ -97,16 +101,20 @@
       myIsSynthetic = false;
       myIsInLibraryContent = false;
     }
+
+    myXStackFrame = myLocation == null ? null : getDebugProcess().getPositionManager().createStackFrame(myLocation);
   }
 
   public int getUiIndex() {
     return myUiIndex;
   }
 
+  @Override
   public StackFrameProxyImpl getFrameProxy() {
     return myFrame;
   }
 
+  @Override
   public DebugProcess getDebugProcess() {
     return myFrame.getVirtualMachine().getDebugProcess();
   }
@@ -140,12 +148,21 @@
     return null;
   }
   
+  @Override
   public String getName() {
     return myName;
   }
 
+  @Override
   protected String calcRepresentation(EvaluationContextImpl context, DescriptorLabelListener descriptorLabelListener) throws EvaluateException {
     DebuggerManagerThreadImpl.assertIsManagerThread();
+
+    if (myXStackFrame != null) {
+      TextTransferable.ColoredStringBuilder builder = new TextTransferable.ColoredStringBuilder();
+      myXStackFrame.customizePresentation(builder);
+      return builder.getBuilder().toString();
+    }
+
     if (myLocation == null) {
       return "";
     }
@@ -159,7 +176,7 @@
         label.append("()");
       }
       if (settings.SHOW_LINE_NUMBER) {
-        String lineNumber = null;
+        String lineNumber;
         try {
           lineNumber = Integer.toString(myLocation.lineNumber());
         }
@@ -172,7 +189,7 @@
         }
       }
       if (settings.SHOW_CLASS_NAME) {
-        String name = null;
+        String name;
         try {
           ReferenceType refType = myLocation.declaringType();
           name = refType != null ? refType.name() : null;
@@ -206,7 +223,7 @@
           label.append(", ");
           label.append(sourceName);
         }
-        catch (AbsentInformationException exception) {
+        catch (AbsentInformationException ignored) {
         }
       }
       return label.toString();
@@ -220,10 +237,12 @@
     return getFrameProxy().equals(d.getFrameProxy());
   }
 
+  @Override
   public boolean isExpandable() {
     return true;
   }
 
+  @Override
   public final void setContext(EvaluationContextImpl context) {
     myIcon = calcIcon();
   }
@@ -246,7 +265,7 @@
         return AllIcons.Debugger.Db_obsolete;
       }
     }
-    catch (EvaluateException e) {
+    catch (EvaluateException ignored) {
     }
     return AllIcons.Debugger.StackFrame;
   }
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/JavaDebuggerEditorsProvider.java b/java/debugger/impl/src/org/jetbrains/java/debugger/JavaDebuggerEditorsProvider.java
index 21cdb36..5df6903 100644
--- a/java/debugger/impl/src/org/jetbrains/java/debugger/JavaDebuggerEditorsProvider.java
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/JavaDebuggerEditorsProvider.java
@@ -1,16 +1,28 @@
 package org.jetbrains.java.debugger;
 
+import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
+import com.intellij.debugger.engine.evaluation.TextWithImports;
+import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
+import com.intellij.debugger.ui.DebuggerExpressionComboBox;
 import com.intellij.ide.highlighter.JavaFileType;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.JavaCodeFragmentFactory;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
+import com.intellij.xdebugger.XSourcePosition;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
 import com.intellij.xdebugger.evaluation.XDebuggerEditorsProviderBase;
+import com.intellij.xdebugger.impl.breakpoints.ui.XDebuggerComboBoxProvider;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-public class JavaDebuggerEditorsProvider extends XDebuggerEditorsProviderBase {
+import javax.swing.*;
+
+public class JavaDebuggerEditorsProvider extends XDebuggerEditorsProviderBase implements XDebuggerComboBoxProvider {
   @NotNull
   @Override
   public FileType getFileType() {
@@ -21,4 +33,77 @@
   protected PsiFile createExpressionCodeFragment(@NotNull Project project, @NotNull String text, @Nullable PsiElement context, boolean isPhysical) {
     return JavaCodeFragmentFactory.getInstance(project).createExpressionCodeFragment(text, context, null, isPhysical);
   }
+
+  @Override
+  public XBreakpointCustomPropertiesPanel<XBreakpoint<?>> createConditionComboBoxPanel(Project project,
+                                                                                       XDebuggerEditorsProvider debuggerEditorsProvider,
+                                                                                       String historyId,
+                                                                                       XSourcePosition sourcePosition) {
+    return new ExpressionComboBoxPanel(project, historyId, sourcePosition) {
+      @Override
+      public void saveTo(@NotNull XBreakpoint<?> breakpoint) {
+        TextWithImports text = myComboBox.getText();
+        final String condition = !text.getText().isEmpty() ? text.toExternalForm() : null;
+        breakpoint.setCondition(condition);
+        if (condition != null) {
+          myComboBox.addRecent(text);
+        }
+      }
+
+      @Override
+      public void loadFrom(@NotNull XBreakpoint<?> breakpoint) {
+        myComboBox.setText(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, StringUtil.notNullize(breakpoint.getCondition())));
+      }
+    };
+  }
+
+  @Override
+  public XBreakpointCustomPropertiesPanel<XBreakpoint<?>> createLogExpressionComboBoxPanel(Project project,
+                                                                                           XDebuggerEditorsProvider debuggerEditorsProvider,
+                                                                                           String historyId,
+                                                                                           XSourcePosition sourcePosition) {
+    return new ExpressionComboBoxPanel(project, historyId, sourcePosition) {
+      @Override
+      public void saveTo(@NotNull XBreakpoint<?> breakpoint) {
+        TextWithImports text = myComboBox.getText();
+        breakpoint.setLogExpression(myComboBox.isEnabled() && !text.getText().isEmpty() ? text.toExternalForm() : null);
+        if (text != null) {
+          myComboBox.addRecent(text);
+        }
+      }
+
+      @Override
+      public void loadFrom(@NotNull XBreakpoint<?> breakpoint) {
+        myComboBox.setText(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, StringUtil.notNullize(breakpoint.getLogExpression())));
+      }
+    };
+  }
+
+  private abstract class ExpressionComboBoxPanel extends XBreakpointCustomPropertiesPanel<XBreakpoint<?>> {
+    protected final DebuggerExpressionComboBox myComboBox;
+
+    private ExpressionComboBoxPanel(Project project,
+                                    String historyId,
+                                    XSourcePosition sourcePosition) {
+      myComboBox = new DebuggerExpressionComboBox(project, historyId);
+      if (sourcePosition != null) {
+        PsiElement element = getContextElement(sourcePosition.getFile(), sourcePosition.getOffset(), project);
+        myComboBox.setContext(element);
+      }
+      else {
+        myComboBox.setContext(null);
+      }
+    }
+
+    @NotNull
+    @Override
+    public JComponent getComponent() {
+      return myComboBox;
+    }
+
+    @Override
+    public void dispose() {
+      myComboBox.dispose();
+    }
+  }
 }
\ No newline at end of file
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapter.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapter.java
deleted file mode 100644
index a670584..0000000
--- a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapter.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package org.jetbrains.java.debugger.breakpoints;
-
-import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
-import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
-import com.intellij.debugger.engine.requests.RequestManagerImpl;
-import com.intellij.debugger.settings.DebuggerSettings;
-import com.intellij.debugger.ui.breakpoints.LineBreakpoint;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.markup.RangeHighlighter;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
-import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
-import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointImpl;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Arrays;
-
-public class JavaBreakpointAdapter extends JavaBreakpointAdapterBase {
-  private static final Key<LineBreakpoint> OLD_JAVA_BREAKPOINT_KEY = Key.create("oldJavaBreakpoint");
-
-  public JavaBreakpointAdapter(Project project) {
-    super(project);
-  }
-
-  @Override
-  protected void configureCreatedBreakpoint(LineBreakpoint oldBreakpoint, XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    oldBreakpoint.SUSPEND_POLICY = transformSuspendPolicy(breakpoint);
-    applyCondition(oldBreakpoint, breakpoint);
-    applyFilters(oldBreakpoint, breakpoint);
-  }
-
-  private boolean applyFilters(LineBreakpoint oldBreakpoint, XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    boolean changed = false;
-    JavaBreakpointProperties properties = (JavaBreakpointProperties)breakpoint.getProperties();
-
-    changed |= oldBreakpoint.COUNT_FILTER_ENABLED != properties.COUNT_FILTER_ENABLED;
-    oldBreakpoint.COUNT_FILTER_ENABLED = properties.COUNT_FILTER_ENABLED;
-
-    changed |= oldBreakpoint.COUNT_FILTER != properties.COUNT_FILTER;
-    oldBreakpoint.COUNT_FILTER = properties.COUNT_FILTER;
-
-    changed |= oldBreakpoint.CLASS_FILTERS_ENABLED != properties.CLASS_FILTERS_ENABLED;
-    oldBreakpoint.CLASS_FILTERS_ENABLED = properties.CLASS_FILTERS_ENABLED;
-
-    changed |= !Arrays.equals(oldBreakpoint.getClassFilters(), properties.getClassFilters());
-    oldBreakpoint.setClassFilters(properties.getClassFilters());
-
-    changed |= !Arrays.equals(oldBreakpoint.getClassExclusionFilters(), properties.getClassExclusionFilters());
-    oldBreakpoint.setClassExclusionFilters(properties.getClassExclusionFilters());
-
-    changed |= oldBreakpoint.INSTANCE_FILTERS_ENABLED != properties.INSTANCE_FILTERS_ENABLED;
-    oldBreakpoint.INSTANCE_FILTERS_ENABLED = properties.INSTANCE_FILTERS_ENABLED;
-
-    changed |= !Arrays.equals(oldBreakpoint.getInstanceFilters(), properties.getInstanceFilters());
-    oldBreakpoint.setInstanceFilters(properties.getInstanceFilters());
-
-    return changed;
-  }
-
-  private static void applyCondition(LineBreakpoint oldBreakpoint, XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    if (breakpoint.getCondition() != null) {
-      oldBreakpoint.CONDITION_ENABLED = true;
-      oldBreakpoint.setCondition(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, breakpoint.getCondition()));
-    }
-    else {
-      oldBreakpoint.CONDITION_ENABLED = false;
-      if (!StringUtil.isEmptyOrSpaces(oldBreakpoint.getCondition().getText())) {
-        oldBreakpoint.setCondition(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, ""));
-      }
-    }
-  }
-
-  @Override
-  protected void updateBreakpoint(LineBreakpoint jBreakpoint, XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    boolean changed = false;
-    if (jBreakpoint.ENABLED != breakpoint.isEnabled()) {
-      jBreakpoint.ENABLED = breakpoint.isEnabled();
-      changed = true;
-    }
-
-    String suspendPolicy = transformSuspendPolicy(breakpoint);
-    if (jBreakpoint.SUSPEND_POLICY != suspendPolicy) {
-      jBreakpoint.SUSPEND_POLICY = suspendPolicy;
-      changed = true;
-    }
-
-    if (StringUtil.compare(breakpoint.getCondition(), jBreakpoint.getCondition().getText(), false) != 0) {
-      applyCondition(jBreakpoint, breakpoint);
-      changed = true;
-    }
-
-    if (applyFilters(jBreakpoint, breakpoint)) {
-      changed = true;
-    }
-
-    if (jBreakpoint.getSourcePosition().getLine() != breakpoint.getLine()) {
-      jBreakpoint.reload();
-      changed = true;
-    }
-
-    if (changed) {
-      RequestManagerImpl.updateRequests(jBreakpoint);
-      jBreakpoint.updateUI();
-    }
-  }
-
-  @Override
-  protected LineBreakpoint findBreakpoint(XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    return OLD_JAVA_BREAKPOINT_KEY.get(breakpoint);
-  }
-
-  public LineBreakpoint getOrCreate(XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    LineBreakpoint oldBreakpoint = findBreakpoint(breakpoint);
-    if (oldBreakpoint == null) {
-      oldBreakpoint = createBreakpoint(breakpoint);
-      OLD_JAVA_BREAKPOINT_KEY.set(breakpoint, oldBreakpoint);
-    }
-    return oldBreakpoint;
-  }
-
-  @Override
-  public void breakpointRemoved(@NotNull XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    LineBreakpoint jBreakpoint = findBreakpoint(breakpoint);
-    if (jBreakpoint != null) {
-      jBreakpoint.delete();
-    }
-  }
-
-  @Override
-  protected LineBreakpoint doCreateInstance(Project project, Document document, XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    LineBreakpoint lineBreakpoint = new LineBreakpoint(project, ((XLineBreakpointImpl)breakpoint).getHighlighter()) {
-      @Override
-      protected void setEditorFilter(RangeHighlighter highlighter) {
-      }
-    };
-
-    lineBreakpoint.setVisible(false);
-    lineBreakpoint.init();
-    return lineBreakpoint;
-  }
-
-  private static String transformSuspendPolicy(XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    switch (breakpoint.getSuspendPolicy()) {
-      case ALL:
-        return DebuggerSettings.SUSPEND_ALL;
-      case THREAD:
-        return DebuggerSettings.SUSPEND_THREAD;
-      case NONE:
-        return DebuggerSettings.SUSPEND_NONE;
-
-      default:
-        throw new IllegalArgumentException("unknown suspend policy");
-    }
-  }
-}
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapterBase.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapterBase.java
index 6b24935..686de9a 100644
--- a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapterBase.java
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapterBase.java
@@ -56,11 +56,11 @@
     LineBreakpoint oldBreakpoint = doCreateInstance(project, document, breakpoint);
     oldBreakpoint.setVisible(false);
     oldBreakpoint.updateUI();
-    oldBreakpoint.ENABLED = breakpoint.isEnabled();
+    oldBreakpoint.setEnabled(breakpoint.isEnabled());
     return oldBreakpoint;
   }
 
-  protected LineBreakpoint doCreateInstance(Project project, Document document, XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    return LineBreakpoint.create(project, document, breakpoint.getLine());
+  protected LineBreakpoint doCreateInstance(Project project, Document document, XLineBreakpoint<XBreakpointProperties> xBreakpoint) {
+    return LineBreakpoint.create(project, xBreakpoint);
   }
 }
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.form b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.form
similarity index 99%
rename from java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.form
rename to java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.form
index db560b3..3950767 100644
--- a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.form
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.form
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.java.debugger.breakpoints.JavaBreakpointPropertiesPanel">
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.java.debugger.breakpoints.JavaBreakpointFiltersPanel">
   <grid id="27dc6" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
     <margin top="0" left="0" bottom="0" right="0"/>
     <constraints>
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.java
similarity index 94%
rename from java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.java
rename to java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.java
index e575973..2afcf0f 100644
--- a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.java
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.java
@@ -26,11 +26,11 @@
 import com.intellij.ui.MultiLineTooltipUI;
 import com.intellij.ui.classFilter.ClassFilter;
 import com.intellij.xdebugger.XSourcePosition;
-import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
-import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
 import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;
 
 import javax.swing.*;
 import java.awt.*;
@@ -44,7 +44,7 @@
 /**
  * @author egor
  */
-public class JavaBreakpointPropertiesPanel extends XBreakpointCustomPropertiesPanel<XLineBreakpoint<XBreakpointProperties>> {
+public class JavaBreakpointFiltersPanel<T extends JavaBreakpointProperties, B extends XBreakpoint<T>> extends XBreakpointCustomPropertiesPanel<B> {
   private JPanel myConditionsPanel;
   private JPanel myInstanceFiltersPanel;
   private JCheckBox myInstanceFiltersCheckBox;
@@ -66,7 +66,7 @@
 
   private PsiClass myBreakpointPsiClass;
 
-  public JavaBreakpointPropertiesPanel(Project project) {
+  public JavaBreakpointFiltersPanel(Project project) {
     myProject = project;
     myInstanceFiltersField = new FieldPanel(new MyTextField(), "", null,
                                             new ActionListener() {
@@ -135,8 +135,8 @@
   }
 
   @Override
-  public boolean isVisibleOnPopup(@NotNull XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    JavaBreakpointProperties properties = (JavaBreakpointProperties)breakpoint.getProperties();
+  public boolean isVisibleOnPopup(@NotNull B breakpoint) {
+    JavaBreakpointProperties properties = breakpoint.getProperties();
     if (properties != null) {
       return properties.COUNT_FILTER_ENABLED || properties.CLASS_FILTERS_ENABLED || properties.INSTANCE_FILTERS_ENABLED;
     }
@@ -144,8 +144,8 @@
   }
 
   @Override
-  public void saveTo(@NotNull XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    JavaBreakpointProperties properties = (JavaBreakpointProperties)breakpoint.getProperties();
+  public void saveTo(@NotNull B breakpoint) {
+    JavaBreakpointProperties properties = breakpoint.getProperties();
     if (properties == null) {
       return;
     }
@@ -179,8 +179,8 @@
   }
 
   @Override
-  public void loadFrom(@NotNull XLineBreakpoint<XBreakpointProperties> breakpoint) {
-    JavaBreakpointProperties properties = (JavaBreakpointProperties)breakpoint.getProperties();
+  public void loadFrom(@NotNull B breakpoint) {
+    JavaBreakpointProperties properties = breakpoint.getProperties();
     if (properties != null) {
       if (properties.COUNT_FILTER > 0) {
         myPassCountField.setText(Integer.toString(properties.COUNT_FILTER));
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointType.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointType.java
deleted file mode 100644
index 5e55a49..0000000
--- a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointType.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.jetbrains.java.debugger.breakpoints;
-
-import com.intellij.debugger.DebuggerBundle;
-import com.intellij.debugger.engine.DebuggerUtils;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.StdFileTypes;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
-import com.intellij.util.SystemProperties;
-import com.intellij.xdebugger.XDebuggerUtil;
-import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
-import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
-import com.intellij.xdebugger.breakpoints.XLineBreakpointTypeBase;
-import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
-import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.java.debugger.JavaDebuggerEditorsProvider;
-
-import java.util.List;
-
-public class JavaBreakpointType extends XLineBreakpointTypeBase {
-  public JavaBreakpointType() {
-    super("java", DebuggerBundle.message("java.breakpoint.title"), new JavaDebuggerEditorsProvider());
-  }
-
-  @Override
-  public boolean canPutAt(@NotNull final VirtualFile file, final int line, @NotNull Project project) {
-    return SystemProperties.getBooleanProperty("java.debugger.xBreakpoint", false) &&
-           doCanPutAt(PsiManager.getInstance(project).findFile(file));
-  }
-
-  @Override
-  public boolean isSuspendThreadSupported() {
-    return true;
-  }
-
-  @Override
-  public List<XBreakpointGroupingRule<XLineBreakpoint<XBreakpointProperties>, ?>> getGroupingRules() {
-    return XDebuggerUtil.getInstance().getGroupingByFileRuleAsList();
-  }
-
-  @Contract("null -> false")
-  public static boolean doCanPutAt(@Nullable PsiFile psiFile) {
-    // JSPX supports jvm debugging, but not in XHTML files
-    if (psiFile == null || psiFile.getVirtualFile().getFileType() == StdFileTypes.XHTML) {
-      return false;
-    }
-
-    FileType fileType = psiFile.getFileType();
-    return StdFileTypes.CLASS.equals(fileType) || DebuggerUtils.supportsJVMDebugging(fileType) || DebuggerUtils.supportsJVMDebugging(psiFile);
-  }
-
-  @Nullable
-  @Override
-  public XBreakpointProperties createProperties() {
-    return new JavaBreakpointProperties();
-  }
-
-  @Nullable
-  @Override
-  public XBreakpointProperties createBreakpointProperties(@NotNull VirtualFile file, int line) {
-    return new JavaBreakpointProperties();
-  }
-
-  @Nullable
-  @Override
-  public XBreakpointCustomPropertiesPanel<XLineBreakpoint<XBreakpointProperties>> createCustomRightPropertiesPanel(@NotNull Project project) {
-    return new JavaBreakpointPropertiesPanel(project);
-  }
-
-
-}
\ No newline at end of file
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointProperties.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaBreakpointProperties.java
similarity index 71%
rename from java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointProperties.java
rename to java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaBreakpointProperties.java
index e2f3202..daab63a 100644
--- a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointProperties.java
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaBreakpointProperties.java
@@ -13,27 +13,36 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.jetbrains.java.debugger.breakpoints;
+package org.jetbrains.java.debugger.breakpoints.properties;
 
 import com.intellij.debugger.InstanceFilter;
 import com.intellij.ui.classFilter.ClassFilter;
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.OptionTag;
+import com.intellij.util.xmlb.annotations.Tag;
 import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
 import org.jetbrains.annotations.Nullable;
 
 /**
  * @author egor
  */
-public class JavaBreakpointProperties extends XBreakpointProperties<JavaBreakpointProperties> {
+public class JavaBreakpointProperties<T extends JavaBreakpointProperties> extends XBreakpointProperties<T> {
+  @OptionTag("count-filter-enabled")
   public boolean COUNT_FILTER_ENABLED     = false;
+  @OptionTag("count-filter")
   public int COUNT_FILTER = 0;
 
+  @OptionTag("class-filters-enabled")
   public boolean CLASS_FILTERS_ENABLED    = false;
   private ClassFilter[] myClassFilters;
   private ClassFilter[] myClassExclusionFilters;
 
+  @OptionTag("instance-filters-enabled")
   public boolean INSTANCE_FILTERS_ENABLED = false;
   private InstanceFilter[] myInstanceFilters;
 
+  @Tag("instance-filters")
+  @AbstractCollection(surroundWithTag = false)
   public InstanceFilter[] getInstanceFilters() {
     return myInstanceFilters != null ? myInstanceFilters : InstanceFilter.EMPTY_ARRAY;
   }
@@ -42,13 +51,15 @@
     myInstanceFilters = instanceFilters;
   }
 
-  protected void addInstanceFilter(long l) {
+  public void addInstanceFilter(long l) {
     final InstanceFilter[] filters = new InstanceFilter[myInstanceFilters.length + 1];
     System.arraycopy(myInstanceFilters, 0, filters, 0, myInstanceFilters.length);
     filters[myInstanceFilters.length] = InstanceFilter.create(String.valueOf(l));
     myInstanceFilters = filters;
   }
 
+  @Tag("class-filters")
+  @AbstractCollection(surroundWithTag = false)
   public final ClassFilter[] getClassFilters() {
     return myClassFilters != null ? myClassFilters : ClassFilter.EMPTY_ARRAY;
   }
@@ -57,6 +68,8 @@
     myClassFilters = classFilters;
   }
 
+  @Tag("class-exclusion-filters")
+  @AbstractCollection(surroundWithTag = false)
   public ClassFilter[] getClassExclusionFilters() {
     return myClassExclusionFilters != null ? myClassExclusionFilters : ClassFilter.EMPTY_ARRAY;
   }
@@ -67,20 +80,20 @@
 
   @Nullable
   @Override
-  public JavaBreakpointProperties getState() {
-    return this;
+  public T getState() {
+    return (T)this;
   }
 
   @Override
-  public void loadState(JavaBreakpointProperties state) {
+  public void loadState(T state) {
     COUNT_FILTER_ENABLED = state.COUNT_FILTER_ENABLED;
     COUNT_FILTER = state.COUNT_FILTER;
 
     CLASS_FILTERS_ENABLED = state.CLASS_FILTERS_ENABLED;
-    myClassFilters = state.myClassFilters;
-    myClassExclusionFilters = state.myClassExclusionFilters;
+    myClassFilters = state.getClassFilters();
+    myClassExclusionFilters = state.getClassExclusionFilters();
 
     INSTANCE_FILTERS_ENABLED = state.INSTANCE_FILTERS_ENABLED;
-    myInstanceFilters = state.myInstanceFilters;
+    myInstanceFilters = state.getInstanceFilters();
   }
 }
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaExceptionBreakpointProperties.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaExceptionBreakpointProperties.java
new file mode 100644
index 0000000..e3b893e
--- /dev/null
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaExceptionBreakpointProperties.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ * 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 org.jetbrains.java.debugger.breakpoints.properties;
+
+import com.intellij.util.xmlb.annotations.Attribute;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author egor
+ */
+public class JavaExceptionBreakpointProperties extends JavaBreakpointProperties<JavaExceptionBreakpointProperties> {
+  public boolean NOTIFY_CAUGHT   = true;
+  public boolean NOTIFY_UNCAUGHT = true;
+
+  @Attribute("class")
+  public String myQualifiedName;
+
+  @Attribute("package")
+  public String myPackageName;
+
+  public JavaExceptionBreakpointProperties(String qualifiedName, String packageName) {
+    myQualifiedName = qualifiedName;
+    myPackageName = packageName;
+  }
+
+  public JavaExceptionBreakpointProperties() {
+  }
+
+  @Nullable
+  @Override
+  public JavaExceptionBreakpointProperties getState() {
+    return this;
+  }
+
+  @Override
+  public void loadState(JavaExceptionBreakpointProperties state) {
+    super.loadState(state);
+
+    NOTIFY_CAUGHT = state.NOTIFY_CAUGHT;
+    NOTIFY_UNCAUGHT = state.NOTIFY_UNCAUGHT;
+    myQualifiedName = state.myQualifiedName;
+    myPackageName = state.myPackageName;
+  }
+}
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaFieldBreakpointProperties.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaFieldBreakpointProperties.java
new file mode 100644
index 0000000..13b760e
--- /dev/null
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaFieldBreakpointProperties.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ * 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 org.jetbrains.java.debugger.breakpoints.properties;
+
+import com.intellij.util.xmlb.annotations.Attribute;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author egor
+ */
+public class JavaFieldBreakpointProperties extends JavaBreakpointProperties<JavaFieldBreakpointProperties> {
+  public boolean WATCH_MODIFICATION = true;
+  public boolean WATCH_ACCESS       = false;
+
+  @Attribute("field")
+  public String myFieldName;
+
+  @Attribute("class")
+  public String myClassName;
+
+  public JavaFieldBreakpointProperties(String fieldName, String className) {
+    myFieldName = fieldName;
+    myClassName = className;
+  }
+
+  public JavaFieldBreakpointProperties() {
+  }
+
+  @Nullable
+  @Override
+  public JavaFieldBreakpointProperties getState() {
+    return this;
+  }
+
+  @Override
+  public void loadState(JavaFieldBreakpointProperties state) {
+    super.loadState(state);
+
+    WATCH_MODIFICATION = state.WATCH_MODIFICATION;
+    WATCH_ACCESS = state.WATCH_ACCESS;
+    myFieldName = state.myFieldName;
+    myClassName = state.myClassName;
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaLineBreakpointProperties.java
similarity index 61%
copy from platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
copy to java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaLineBreakpointProperties.java
index 72c585b..9a89234 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaLineBreakpointProperties.java
@@ -13,18 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk2;
-
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.util.Consumer;
+package org.jetbrains.java.debugger.breakpoints.properties;
 
 /**
- * @author traff
+ * @author egor
  */
-public interface RemoteSdkProducer<T extends RemoteSdkCredentials> {
-  T getRemoteSdkCredentials() throws InterruptedException;
-  
-  void produceRemoteSdkCredentials(Consumer<T> remoteSdkConsumer);
-
-  Object getRemoteSdkDataKey();
+public class JavaLineBreakpointProperties extends JavaBreakpointProperties<JavaLineBreakpointProperties> {
 }
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaMethodBreakpointProperties.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaMethodBreakpointProperties.java
new file mode 100644
index 0000000..9392b56
--- /dev/null
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaMethodBreakpointProperties.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ * 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 org.jetbrains.java.debugger.breakpoints.properties;
+
+import com.intellij.util.xmlb.annotations.Attribute;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author egor
+ */
+public class JavaMethodBreakpointProperties extends JavaBreakpointProperties<JavaMethodBreakpointProperties> {
+  @Attribute("class")
+  public String myClassPattern;
+
+  @Attribute("method")
+  public String myMethodName;
+
+  public boolean WATCH_ENTRY = true;
+  public boolean WATCH_EXIT  = true;
+
+  public JavaMethodBreakpointProperties(String classPattern, String methodName) {
+    myClassPattern = classPattern;
+    myMethodName = methodName;
+  }
+
+  public JavaMethodBreakpointProperties() {
+  }
+
+  @Nullable
+  @Override
+  public JavaMethodBreakpointProperties getState() {
+    return this;
+  }
+
+  @Override
+  public void loadState(JavaMethodBreakpointProperties state) {
+    super.loadState(state);
+
+    myClassPattern = state.myClassPattern;
+    myMethodName = state.myMethodName;
+
+    WATCH_ENTRY = state.WATCH_ENTRY;
+    WATCH_EXIT = state.WATCH_EXIT;
+  }
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/PositionManagerEx.java b/java/debugger/openapi/src/com/intellij/debugger/PositionManagerEx.java
new file mode 100644
index 0000000..c1faee1
--- /dev/null
+++ b/java/debugger/openapi/src/com/intellij/debugger/PositionManagerEx.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger;
+
+import com.intellij.xdebugger.frame.XStackFrame;
+import com.sun.jdi.Location;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class PositionManagerEx implements PositionManager {
+  @Nullable
+  public abstract XStackFrame createStackFrame(@NotNull Location location);
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcess.java b/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcess.java
index 66fea2d..43c7fd4 100644
--- a/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcess.java
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/DebugProcess.java
@@ -16,6 +16,7 @@
 package com.intellij.debugger.engine;
 
 import com.intellij.debugger.PositionManager;
+import com.intellij.debugger.PositionManagerEx;
 import com.intellij.debugger.engine.evaluation.EvaluateException;
 import com.intellij.debugger.engine.evaluation.EvaluationContext;
 import com.intellij.debugger.engine.jdi.VirtualMachineProxy;
@@ -44,7 +45,7 @@
 
   RequestManager getRequestsManager();
 
-  PositionManager getPositionManager();
+  PositionManagerEx getPositionManager();
 
   VirtualMachineProxy getVirtualMachineProxy();
 
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/JSR45PositionManager.java b/java/debugger/openapi/src/com/intellij/debugger/engine/JSR45PositionManager.java
index 1697684..b200e0e 100644
--- a/java/debugger/openapi/src/com/intellij/debugger/engine/JSR45PositionManager.java
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/JSR45PositionManager.java
@@ -80,6 +80,7 @@
     return myStratumId;
   }
 
+  @Override
   public SourcePosition getSourcePosition(final Location location) throws NoDataException {
     SourcePosition sourcePosition = null;
 
@@ -110,6 +111,7 @@
     return location.lineNumber(myStratumId);
   }
 
+  @Override
   @NotNull
   public List<ReferenceType> getAllClasses(SourcePosition classPosition) throws NoDataException {
     checkSourcePositionFileType(classPosition);
@@ -138,6 +140,7 @@
     }
   }
 
+  @Override
   @NotNull
   public List<Location> locationsOfLine(final ReferenceType type, final SourcePosition position) throws NoDataException {
     List<Location> locations = locationsOfClassAt(type, position);
@@ -149,6 +152,7 @@
     checkSourcePositionFileType(position);
 
     return ApplicationManager.getApplication().runReadAction(new Computable<List<Location>>() {
+      @Override
       public List<Location> compute() {
         try {
           final List<String> relativePaths = getRelativeSourePathsByType(type);
@@ -165,7 +169,7 @@
         }
         catch(ClassNotPreparedException ignored) {                                                                                                           
         }
-        catch (InternalError e) {
+        catch (InternalError ignored) {
           myDebugProcess.getExecutionResult().getProcessHandler().notifyTextAvailable(
             DebuggerBundle.message("internal.error.locations.of.line", type.name()), ProcessOutputTypes.SYSTEM);
         }
@@ -176,7 +180,7 @@
       // This is needed because some servers (e.g. WebSphere) put not exact file name such as 'A.jsp  '
       private String getSourceName(final String name, final ReferenceType type) throws AbsentInformationException {
         for(String sourceNameFromType: type.sourceNames(myStratumId)) {
-          if (sourceNameFromType.indexOf(name) >= 0) {
+          if (sourceNameFromType.contains(name)) {
             return sourceNameFromType;
           }
         }
@@ -199,11 +203,13 @@
     return type.locationsOfLine(myStratumId, fileName, lineNumber);
   }
 
+  @Override
   public ClassPrepareRequest createPrepareRequest(final ClassPrepareRequestor requestor, final SourcePosition position)
     throws NoDataException {
     checkSourcePositionFileType(position);
 
     return myDebugProcess.getRequestsManager().createClassPrepareRequest(new ClassPrepareRequestor() {
+      @Override
       public void processClassPrepare(DebugProcess debuggerProcess, ReferenceType referenceType) {
         onClassPrepare(debuggerProcess, referenceType, position, requestor);
       }
@@ -217,7 +223,7 @@
         requestor.processClassPrepare(debuggerProcess, referenceType);
       }
     }
-    catch (NoDataException e) {
+    catch (NoDataException ignored) {
     }
   }
 
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/StackFrameProxy.java b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/StackFrameProxy.java
index 7e0b6ee..511b1af 100644
--- a/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/StackFrameProxy.java
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/jdi/StackFrameProxy.java
@@ -19,6 +19,7 @@
 import com.sun.jdi.ClassLoaderReference;
 import com.sun.jdi.Location;
 import com.sun.jdi.StackFrame;
+import org.jetbrains.annotations.Nullable;
 
 public interface StackFrameProxy extends ObjectReferenceProxy{
   StackFrame getStackFrame() throws EvaluateException;
@@ -27,6 +28,7 @@
 
   VirtualMachineProxy getVirtualMachine();
 
+  @Nullable
   Location location() throws EvaluateException;
 
   ClassLoaderReference getClassLoader() throws EvaluateException;
diff --git a/java/idea-ui/src/com/intellij/ide/impl/ProjectStructureSelectInTarget.java b/java/idea-ui/src/com/intellij/ide/impl/ProjectStructureSelectInTarget.java
index d282c68..70457eb 100644
--- a/java/idea-ui/src/com/intellij/ide/impl/ProjectStructureSelectInTarget.java
+++ b/java/idea-ui/src/com/intellij/ide/impl/ProjectStructureSelectInTarget.java
@@ -18,6 +18,7 @@
 import com.intellij.facet.*;
 import com.intellij.ide.*;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.module.ModuleManager;
 import com.intellij.openapi.project.DumbAware;
@@ -48,7 +49,8 @@
       final Object o = ((WrappingVirtualFile)file).getWrappedObject(context.getProject());
       return o instanceof Facet;
     }
-    return fileIndex.isInContent(file) || fileIndex.isInLibraryClasses(file) || fileIndex.isInLibrarySource(file);
+    return fileIndex.isInContent(file) || fileIndex.isInLibraryClasses(file) || fileIndex.isInLibrarySource(file)
+           || StdFileTypes.IDEA_MODULE.equals(file.getFileType()) && findModuleByModuleFile(context.getProject(), file) != null;
   }
 
   @Override
@@ -64,8 +66,9 @@
       module = facet == null? null : facet.getModule();
     }
     else {
+      Module moduleByIml = file.getFileType().equals(StdFileTypes.IDEA_MODULE) ? findModuleByModuleFile(project, file) : null;
       final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
-      module = fileIndex.getModuleForFile(file);
+      module = moduleByIml != null ? moduleByIml : fileIndex.getModuleForFile(file);
       facet = fileIndex.isInSourceContent(file) ? null : findFacet(project, file);
     }
     if (module != null || facet != null) {
@@ -95,6 +98,16 @@
   }
 
   @Nullable
+  private static Module findModuleByModuleFile(@NotNull Project project, @NotNull VirtualFile file) {
+    for (Module module : ModuleManager.getInstance(project).getModules()) {
+      if (file.equals(module.getModuleFile())) {
+        return module;
+      }
+    }
+    return null;
+  }
+
+  @Nullable
   private static Facet findFacet(final @NotNull Project project, final @NotNull VirtualFile file) {
     for (FacetTypeId id : FacetTypeRegistry.getInstance().getFacetTypeIds()) {
       if (hasFacetWithRoots(project, id)) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
index 324a222..72ad0f2 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
@@ -406,8 +406,9 @@
     if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && aClass.isInterface() && method.hasModifierProperty(PsiModifier.DEFAULT)) {
       HierarchicalMethodSignature sig = method.getHierarchicalMethodSignature();
       for (HierarchicalMethodSignature methodSignature : sig.getSuperSignatures()) {
-        final PsiClass containingClass = methodSignature.getMethod().getContainingClass();
-        if (containingClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName())) {
+        final PsiMethod objectMethod = methodSignature.getMethod();
+        final PsiClass containingClass = objectMethod.getContainingClass();
+        if (containingClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName()) && objectMethod.hasModifierProperty(PsiModifier.PUBLIC)) {
           return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
             .descriptionAndTooltip("Default method '" + sig.getName() + "' overrides a member of 'java.lang.Object'")
             .range(methodIdentifier)
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
index 4e9d79f..352e745 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
@@ -1324,8 +1324,8 @@
     myHolder.add(GenericsHighlightUtil.checkParametersAllowed(list, myLanguageLevel,myFile));
     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParametersOnRaw(list));
     if (!myHolder.hasErrorResults()) {
-      for (PsiType type : list.getTypeArguments()) {
-        myHolder.add(HighlightUtil.checkDiamondFeature(type, list, myLanguageLevel,myFile));
+      for (PsiTypeElement typeElement : list.getTypeParameterElements()) {
+        myHolder.add(HighlightUtil.checkDiamondFeature(typeElement.getType(), list, myLanguageLevel,myFile));
       }
     }
   }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java
index b9c5d21..a5104f1 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeCastFix.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -33,10 +33,11 @@
 import com.intellij.psi.codeStyle.CodeStyleManager;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import static com.intellij.util.ObjectUtils.assertNotNull;
+
 public class AddTypeCastFix extends LocalQuickFixAndIntentionActionOnPsiElement {
   private final PsiType myType;
 
@@ -75,28 +76,26 @@
     addTypeCast(project, (PsiExpression)startElement, myType);
   }
 
-  private static void addTypeCast(Project project, PsiExpression originalExpression, PsiType type) throws IncorrectOperationException {
+  private static void addTypeCast(Project project, PsiExpression originalExpression, PsiType type) {
     PsiExpression typeCast = createCastExpression(originalExpression, project, type);
     originalExpression.replace(typeCast);
   }
 
-  static PsiExpression createCastExpression(PsiExpression originalExpression, Project project, PsiType type) throws IncorrectOperationException {
+  static PsiExpression createCastExpression(PsiExpression originalExpression, Project project, PsiType type) {
     // remove nested casts
-    PsiElement element = PsiUtil.deparenthesizeExpression(originalExpression);
-    if (element == null){
-      return null;
-    }
+    PsiElement expression = PsiUtil.deparenthesizeExpression(originalExpression);
+    if (expression == null) return null;
+
     PsiElementFactory factory = JavaPsiFacade.getInstance(originalExpression.getProject()).getElementFactory();
-
     PsiTypeCastExpression typeCast = (PsiTypeCastExpression)factory.createExpressionFromText("(Type)value", null);
+    assertNotNull(typeCast.getCastType()).replace(factory.createTypeElement(type));
     typeCast = (PsiTypeCastExpression)CodeStyleManager.getInstance(project).reformat(typeCast);
-    typeCast.getCastType().replace(factory.createTypeElement(type));
 
-    if (element instanceof PsiConditionalExpression) {
-      // we'd better cast one branch of ternary expression if we could
-      PsiConditionalExpression expression = (PsiConditionalExpression)element.copy();
-      PsiExpression thenE = expression.getThenExpression();
-      PsiExpression elseE = expression.getElseExpression();
+    if (expression instanceof PsiConditionalExpression) {
+      // we'd better cast one branch of ternary expression if we can
+      PsiConditionalExpression conditional = (PsiConditionalExpression)expression.copy();
+      PsiExpression thenE = conditional.getThenExpression();
+      PsiExpression elseE = conditional.getElseExpression();
       PsiType thenType = thenE == null ? null : thenE.getType();
       PsiType elseType = elseE == null ? null : elseE.getType();
       if (elseType != null && thenType != null) {
@@ -104,18 +103,20 @@
         boolean replaceElse = !TypeConversionUtil.isAssignable(type, elseType);
         if (replaceThen != replaceElse) {
           if (replaceThen) {
-            typeCast.getOperand().replace(thenE);
+            assertNotNull(typeCast.getOperand()).replace(thenE);
             thenE.replace(typeCast);
           }
           else {
-            typeCast.getOperand().replace(elseE);
+            assertNotNull(typeCast.getOperand()).replace(elseE);
             elseE.replace(typeCast);
           }
-          return expression;
+          return conditional;
         }
       }
     }
-    typeCast.getOperand().replace(element);
+
+    assertNotNull(typeCast.getOperand()).replace(expression);
+
     return typeCast;
   }
 
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeTypeArgumentsFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeTypeArgumentsFix.java
index 76580ad..b4a8d5b 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeTypeArgumentsFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeTypeArgumentsFix.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,14 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/**
- * Created by IntelliJ IDEA.
- * User: cdr
- * Date: Nov 13, 2002
- * Time: 3:26:50 PM
- * To change this template use Options | File Templates.
- */
 package com.intellij.codeInsight.daemon.impl.quickfix;
 
 import com.intellij.codeInsight.FileModificationService;
@@ -32,6 +24,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.TypeConversionUtil;
@@ -39,11 +32,18 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import static com.intellij.util.ObjectUtils.assertNotNull;
+
+/**
+ * @author cdr
+ * @since Nov 13, 2002
+ */
 public class ChangeTypeArgumentsFix implements IntentionAction, HighPriorityAction {
+  private static final Logger LOG = Logger.getInstance("#" + ChangeTypeArgumentsFix.class.getName());
+
   private final PsiMethod myTargetMethod;
   private final PsiClass myPsiClass;
   private final PsiExpression[] myExpressions;
-  private static final Logger LOG = Logger.getInstance("#" + ChangeTypeArgumentsFix.class.getName());
   private final PsiNewExpression myNewExpression;
 
   ChangeTypeArgumentsFix(@NotNull PsiMethod targetMethod,
@@ -116,11 +116,12 @@
     LOG.assertTrue(reference != null, myNewExpression);
     final PsiReferenceParameterList parameterList = reference.getParameterList();
     LOG.assertTrue(parameterList != null, myNewExpression);
+    PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
     PsiTypeElement[] elements = parameterList.getTypeParameterElements();
     for (int i = elements.length - 1; i >= 0; i--) {
-      PsiTypeElement typeElement = elements[i];
-      final PsiType typeArg = psiSubstitutor.substitute(typeParameters[i]);
-      typeElement.replace(JavaPsiFacade.getElementFactory(project).createTypeElement(typeArg));
+      PsiType typeArg = assertNotNull(psiSubstitutor.substitute(typeParameters[i]));
+      PsiElement replaced = elements[i].replace(factory.createTypeElement(typeArg));
+      JavaCodeStyleManager.getInstance(file.getProject()).shortenClassReferences(replaced);
     }
   }
 
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java
index 987f02d..84f704f 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/AddAnnotationPsiFix.java
@@ -64,15 +64,25 @@
   }
 
   @Nullable
-  public static PsiModifierListOwner getContainer(final PsiElement element) {
-    PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false);
-    if (listOwner == null) {
-      final PsiIdentifier psiIdentifier = PsiTreeUtil.getParentOfType(element, PsiIdentifier.class, false);
-      if (psiIdentifier != null && psiIdentifier.getParent() instanceof PsiModifierListOwner) {
-        listOwner = (PsiModifierListOwner)psiIdentifier.getParent();
+  public static PsiModifierListOwner getContainer(final PsiFile file, int offset) {
+    PsiReference reference = file.findReferenceAt(offset);
+    if (reference != null) {
+      PsiElement target = reference.resolve();
+      if (target instanceof PsiMember) {
+        return (PsiMember)target;
       }
     }
-    return listOwner;
+
+    PsiElement element = file.findElementAt(offset);
+
+    PsiModifierListOwner listOwner = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false);
+    if (listOwner != null) return listOwner;
+
+    final PsiIdentifier psiIdentifier = PsiTreeUtil.getParentOfType(element, PsiIdentifier.class, false);
+    if (psiIdentifier != null && psiIdentifier.getParent() instanceof PsiModifierListOwner) {
+      return (PsiModifierListOwner)psiIdentifier.getParent();
+    }
+    return null;
   }
 
   @Override
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/impl/AddNullableNotNullAnnotationFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/impl/AddNullableNotNullAnnotationFix.java
index 6684613..272ce37 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/impl/AddNullableNotNullAnnotationFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/impl/AddNullableNotNullAnnotationFix.java
@@ -41,7 +41,7 @@
     if (!super.isAvailable(project, file, startElement, endElement)) {
       return false;
     }
-    PsiModifierListOwner owner = getContainer(startElement);
+    PsiModifierListOwner owner = getContainer(file, startElement.getTextRange().getStartOffset());
     if (owner == null || AnnotationUtil.isAnnotated(owner, getAnnotationsToRemove()[0], false, false)) {
       return false;
     }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
index ed34940..b89473e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
@@ -22,6 +22,7 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
@@ -97,8 +98,11 @@
                       final String localName = local.getName();
                       if (localName != null && helper.resolveReferencedVariable(localName, aClass) != null) return;
                     }
-                    holder.registerProblem(aClass.getBaseClassReference(), "Anonymous #ref #loc can be replaced with lambda",
-                                           ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new ReplaceWithLambdaFix());
+                    final PsiElement lBrace = aClass.getLBrace();
+                    LOG.assertTrue(lBrace != null);
+                    final TextRange rangeInElement = new TextRange(0, aClass.getStartOffsetInParent() + lBrace.getStartOffsetInParent());
+                    holder.registerProblem(aClass.getParent(), "Anonymous #ref #loc can be replaced with lambda",
+                                           ProblemHighlightType.LIKE_UNUSED_SYMBOL, rangeInElement, new ReplaceWithLambdaFix());
                   }
                 }
               }
@@ -125,8 +129,8 @@
     @Override
     public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
       final PsiElement element = descriptor.getPsiElement();
-      if (element != null) {
-        final PsiAnonymousClass anonymousClass = PsiTreeUtil.getParentOfType(element, PsiAnonymousClass.class);
+      if (element instanceof PsiNewExpression) {
+        final PsiAnonymousClass anonymousClass = ((PsiNewExpression)element).getAnonymousClass();
         LOG.assertTrue(anonymousClass != null);
         ChangeContextUtil.encodeContextInfo(anonymousClass, true);
         final PsiElement lambdaContext = anonymousClass.getParent().getParent();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java
index 6ad6d22..6eec614 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java
@@ -18,10 +18,10 @@
 import com.intellij.codeInsight.daemon.GroupNames;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
 import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.psi.util.RedundantCastUtil;
 import org.jetbrains.annotations.Nls;
@@ -79,8 +79,11 @@
                 if (parent instanceof PsiNewExpression) {
                   final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)parent).getClassOrAnonymousClassReference();
                   if (classReference != null) {
-                    holder.registerProblem(classReference,
-                                           "Anonymous #ref #loc can be replaced with method reference", new ReplaceWithMethodRefFix());
+                    final PsiElement lBrace = aClass.getLBrace();
+                    LOG.assertTrue(lBrace != null);
+                    final TextRange rangeInElement = new TextRange(0, aClass.getStartOffsetInParent() + lBrace.getStartOffsetInParent());
+                    holder.registerProblem(parent,
+                                           "Anonymous #ref #loc can be replaced with method reference", ProblemHighlightType.LIKE_UNUSED_SYMBOL, rangeInElement, new ReplaceWithMethodRefFix());
                   }
                 }
               }
@@ -107,29 +110,31 @@
       @Override
       public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
         final PsiElement element = descriptor.getPsiElement();
-        final PsiAnonymousClass anonymousClass = PsiTreeUtil.getParentOfType(element, PsiAnonymousClass.class);
-        if (anonymousClass == null) return;
-        final PsiMethod[] methods = anonymousClass.getMethods();
-        if (methods.length != 1) return;
+        if (element instanceof PsiNewExpression) {
+          final PsiAnonymousClass anonymousClass = ((PsiNewExpression)element).getAnonymousClass();
+          if (anonymousClass == null) return;
+          final PsiMethod[] methods = anonymousClass.getMethods();
+          if (methods.length != 1) return;
 
-        final PsiParameter[] parameters = methods[0].getParameterList().getParameters();
-        final PsiCallExpression callExpression = LambdaCanBeMethodReferenceInspection
-          .canBeMethodReferenceProblem(methods[0].getBody(), parameters, anonymousClass.getBaseClassType());
-        if (callExpression == null) return;
-        final String methodRefText =
-          LambdaCanBeMethodReferenceInspection.createMethodReferenceText(callExpression, anonymousClass.getBaseClassType(), parameters);
+          final PsiParameter[] parameters = methods[0].getParameterList().getParameters();
+          final PsiCallExpression callExpression = LambdaCanBeMethodReferenceInspection
+            .canBeMethodReferenceProblem(methods[0].getBody(), parameters, anonymousClass.getBaseClassType());
+          if (callExpression == null) return;
+          final String methodRefText =
+            LambdaCanBeMethodReferenceInspection.createMethodReferenceText(callExpression, anonymousClass.getBaseClassType(), parameters);
 
-        if (methodRefText != null) {
-          final String canonicalText = anonymousClass.getBaseClassType().getCanonicalText();
-          final PsiExpression psiExpression = JavaPsiFacade.getElementFactory(project).createExpressionFromText("(" + canonicalText + ")" + methodRefText, anonymousClass);
-
-          PsiElement castExpr = anonymousClass.getParent().replace(psiExpression);
-          if (RedundantCastUtil.isCastRedundant((PsiTypeCastExpression)castExpr)) {
-            final PsiExpression operand = ((PsiTypeCastExpression)castExpr).getOperand();
-            LOG.assertTrue(operand != null);
-            castExpr = castExpr.replace(operand);
+          if (methodRefText != null) {
+            final String canonicalText = anonymousClass.getBaseClassType().getCanonicalText();
+            final PsiExpression psiExpression = JavaPsiFacade.getElementFactory(project).createExpressionFromText("(" + canonicalText + ")" + methodRefText, anonymousClass);
+  
+            PsiElement castExpr = anonymousClass.getParent().replace(psiExpression);
+            if (RedundantCastUtil.isCastRedundant((PsiTypeCastExpression)castExpr)) {
+              final PsiExpression operand = ((PsiTypeCastExpression)castExpr).getOperand();
+              LOG.assertTrue(operand != null);
+              castExpr = castExpr.replace(operand);
+            }
+            JavaCodeStyleManager.getInstance(project).shortenClassReferences(castExpr);
           }
-          JavaCodeStyleManager.getInstance(project).shortenClassReferences(castExpr);
         }
       }
     }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java
index 8a8a6db..9bc2a6e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java
@@ -88,27 +88,7 @@
   protected static PsiCallExpression canBeMethodReferenceProblem(@Nullable final PsiElement body,
                                                                  final PsiParameter[] parameters,
                                                                  PsiType functionalInterfaceType) {
-    PsiCallExpression methodCall = null;
-    if (body instanceof PsiCallExpression) {
-      methodCall = (PsiCallExpression)body;
-    }
-    else if (body instanceof PsiCodeBlock) {
-      final PsiStatement[] statements = ((PsiCodeBlock)body).getStatements();
-      if (statements.length == 1) {
-        if (statements[0] instanceof PsiReturnStatement) {
-          final PsiExpression returnValue = ((PsiReturnStatement)statements[0]).getReturnValue();
-          if (returnValue instanceof PsiCallExpression) {
-            methodCall = (PsiCallExpression)returnValue;
-          }
-        }
-        else if (statements[0] instanceof PsiExpressionStatement) {
-          final PsiExpression expr = ((PsiExpressionStatement)statements[0]).getExpression();
-          if (expr instanceof PsiCallExpression) {
-            methodCall = (PsiCallExpression)expr;
-          }
-        }
-      }
-    }
+    PsiCallExpression methodCall = extractMethodCallFromBlock(body);
 
     if (methodCall != null) {
       final PsiExpressionList argumentList = methodCall.getArgumentList();
@@ -218,6 +198,40 @@
     return null;
   }
 
+  public static PsiCallExpression extractMethodCallFromBlock(PsiElement body) {
+    PsiCallExpression methodCall = null;
+    if (body instanceof PsiCallExpression) {
+      methodCall = (PsiCallExpression)body;
+    }
+    else if (body instanceof PsiCodeBlock) {
+      final PsiStatement[] statements = ((PsiCodeBlock)body).getStatements();
+      if (statements.length == 1) {
+        if (statements[0] instanceof PsiReturnStatement) {
+          final PsiExpression returnValue = ((PsiReturnStatement)statements[0]).getReturnValue();
+          if (returnValue instanceof PsiCallExpression) {
+            methodCall = (PsiCallExpression)returnValue;
+          }
+        }
+        else if (statements[0] instanceof PsiExpressionStatement) {
+          final PsiExpression expr = ((PsiExpressionStatement)statements[0]).getExpression();
+          if (expr instanceof PsiCallExpression) {
+            methodCall = (PsiCallExpression)expr;
+          }
+        }
+      }
+    }
+    else if (body instanceof PsiBlockStatement) {
+      return extractMethodCallFromBlock(((PsiBlockStatement)body).getCodeBlock());
+    }
+    else if (body instanceof PsiExpressionStatement) {
+      final PsiExpression expression = ((PsiExpressionStatement)body).getExpression();
+      if (expression instanceof PsiCallExpression) {
+        methodCall = (PsiCallExpression)expression;
+      }
+    }
+    return methodCall;
+  }
+
   @Nullable
   private static PsiMethod ensureNonAmbiguousMethod(PsiParameter[] parameters, @NotNull PsiMethod psiMethod) {
     String methodName = psiMethod.getName();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java
index 8101d16..919fb4e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java
@@ -21,7 +21,9 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.controlFlow.*;
+import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
@@ -106,9 +108,14 @@
                     }
                   });
   
-                  if (effectivelyFinal[0] && !isTrivial(body, statement.getIterationParameter(), iteratedValueType)) {
-                    holder.registerProblem(iteratedValue, "Can be replaced with foreach call",
-                                           ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new ReplaceWithForeachCallFix());
+                  if (effectivelyFinal[0]) {
+                    if (isCollectCall(body)) {
+                      holder.registerProblem(iteratedValue, "Can be replaced with collect call",
+                                             ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new ReplaceWithCollectCallFix());
+                    } else if (!isTrivial(body, statement.getIterationParameter(), iteratedValueType)) {
+                      holder.registerProblem(iteratedValue, "Can be replaced with foreach call",
+                                             ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new ReplaceWithForeachCallFix());
+                    }
                   }
                 }
               }
@@ -121,10 +128,46 @@
     };
   }
 
+  private static boolean isCollectCall(PsiStatement body) {
+    final PsiMethodCallExpression methodCallExpression = extractAddCall(body);
+    if (methodCallExpression != null) {
+      final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+      final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
+      PsiClass qualifierClass = null;
+      if (qualifierExpression instanceof PsiReferenceExpression) {
+        qualifierClass = PsiUtil.resolveClassInType(qualifierExpression.getType());
+      } else if (qualifierExpression == null) {
+        final PsiClass enclosingClass = PsiTreeUtil.getParentOfType(body, PsiClass.class);
+        if (PsiUtil.getEnclosingStaticElement(body, enclosingClass) == null) {
+          qualifierClass = enclosingClass;
+        }
+      }
+
+      if (qualifierClass != null && 
+          InheritanceUtil.isInheritor(qualifierClass, false, CommonClassNames.JAVA_UTIL_COLLECTION)) {
+
+        final PsiElement resolve = methodExpression.resolve();
+        if (resolve instanceof PsiMethod &&
+            "add".equals(((PsiMethod)resolve).getName()) &&
+            ((PsiMethod)resolve).getParameterList().getParametersCount() == 1) {
+          final PsiExpression[] args = methodCallExpression.getArgumentList().getExpressions();
+          if (args.length == 1) {
+            if (args[0] instanceof PsiCallExpression) {
+              final PsiMethod method = ((PsiCallExpression)args[0]).resolveMethod();
+              return method != null && !method.hasTypeParameters();
+            }
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+  
   private static boolean isTrivial(PsiStatement body, PsiParameter parameter, PsiType iteratedValueType) {
     final PsiIfStatement ifStatement = extractIfStatement(body);
     //stream
-    if (ifStatement != null && ifStatement.getElseBranch() == null && ifStatement.getThenBranch() != null && 
+    if (ifStatement != null &&
         InheritanceUtil.isInheritor(iteratedValueType, CommonClassNames.JAVA_UTIL_COLLECTION)) {
       return false;
     }
@@ -157,11 +200,12 @@
 
           String foreEachText = body.getText();
           String iterated = iteratedValue.getText();
-          if (ifStmt != null && ifStmt.getElseBranch() == null) {
+          if (ifStmt != null) {
             final PsiExpression condition = ifStmt.getCondition();
             if (condition != null) {
               final PsiStatement thenBranch = ifStmt.getThenBranch();
-              if (thenBranch != null && InheritanceUtil.isInheritor(iteratedValue.getType(), CommonClassNames.JAVA_UTIL_COLLECTION)) {
+              LOG.assertTrue(thenBranch != null);
+              if (InheritanceUtil.isInheritor(iteratedValue.getType(), CommonClassNames.JAVA_UTIL_COLLECTION)) {
                 body = thenBranch;
                 foreEachText = thenBranch.getText();
                 iterated += ".stream().filter(" + parameter.getName() + " -> " + condition.getText() +")";
@@ -170,8 +214,16 @@
           }
 
           final PsiParameter[] parameters = {parameter};
-          final PsiCallExpression expression = LambdaCanBeMethodReferenceInspection.canBeMethodReferenceProblem(body instanceof PsiBlockStatement ? ((PsiBlockStatement)body).getCodeBlock() : body, parameters, null);
-          final String methodReferenceText = LambdaCanBeMethodReferenceInspection.createMethodReferenceText(expression, null, parameters);
+          String methodReferenceText = null;
+          final PsiCallExpression callExpression = LambdaCanBeMethodReferenceInspection.extractMethodCallFromBlock(body);
+          if (callExpression != null) {
+            final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
+            final PsiClass consumerClass = psiFacade.findClass("java.util.function.Consumer", GlobalSearchScope.allScope(project));
+            final PsiClassType functionalType = consumerClass != null ? psiFacade.getElementFactory().createType(consumerClass, callExpression.getType()) : null;
+
+            final PsiCallExpression toConvertCall = LambdaCanBeMethodReferenceInspection.canBeMethodReferenceProblem(body instanceof PsiBlockStatement ? ((PsiBlockStatement)body).getCodeBlock() : body, parameters, functionalType);
+            methodReferenceText = LambdaCanBeMethodReferenceInspection.createMethodReferenceText(toConvertCall, functionalType, parameters);
+          }
           final String lambdaText = parameter.getName() + " -> " + foreEachText;
           final String codeBlock8 = methodReferenceText != null ? methodReferenceText : lambdaText;
           PsiExpressionStatement callStatement = (PsiExpressionStatement)JavaPsiFacade.getElementFactory(project).createStatementFromText(iterated + ".forEach(" + codeBlock8 + ");", foreachStatement);
@@ -191,6 +243,98 @@
     }
   }
 
+  private static class ReplaceWithCollectCallFix implements LocalQuickFix {
+    @NotNull
+    @Override
+    public String getName() {
+      return getFamilyName();
+    }
+
+    @NotNull
+    @Override
+    public String getFamilyName() {
+      return "Replace with collect";
+    }
+
+    @Override
+    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+      final PsiForeachStatement foreachStatement = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiForeachStatement.class);
+      if (foreachStatement != null) {
+        PsiStatement body = foreachStatement.getBody();
+        final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
+        if (body != null && iteratedValue != null) {
+          final PsiParameter parameter = foreachStatement.getIterationParameter();
+
+          final PsiIfStatement ifStatement = extractIfStatement(body);
+          final PsiMethodCallExpression methodCallExpression = extractAddCall(body);
+          String iteration = iteratedValue.getText() + ".stream()";
+          if (ifStatement != null) {
+            final PsiExpression condition = ifStatement.getCondition();
+            if (condition != null) {
+              iteration += ".filter(" + parameter.getName() + " -> " + condition.getText() +")";
+            }
+          }
+          iteration +=".map(";
+
+          final PsiExpression mapperCall = methodCallExpression.getArgumentList().getExpressions()[0];
+
+          final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
+          final PsiClass functionClass = psiFacade.findClass("java.util.function.Function", GlobalSearchScope.allScope(project));
+          final PsiClassType functionalInterfaceType = functionClass != null ? psiFacade.getElementFactory().createType(functionClass, parameter.getType(), mapperCall.getType()) : null;
+          final PsiCallExpression toConvertCall = LambdaCanBeMethodReferenceInspection.canBeMethodReferenceProblem(mapperCall,
+                                                                                                                   new PsiParameter[]{
+                                                                                                                     parameter},
+                                                                                                                   functionalInterfaceType);
+          final String methodReferenceText = LambdaCanBeMethodReferenceInspection.createMethodReferenceText(toConvertCall, functionalInterfaceType, new PsiParameter[]{parameter});
+          if (methodReferenceText != null) {
+            iteration += methodReferenceText;
+          } else {
+            iteration += parameter.getName() + " -> " + mapperCall.getText();
+          }
+          iteration += ").collect(java.util.stream.Collectors.";
+
+          String variableName = null;
+          PsiExpression initializer = null;
+          final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression();
+          if (qualifierExpression instanceof PsiReferenceExpression) {
+            final PsiElement resolve = ((PsiReferenceExpression)qualifierExpression).resolve();
+            if (resolve instanceof PsiVariable) {
+              if (resolve instanceof PsiLocalVariable && foreachStatement.equals(PsiTreeUtil.skipSiblingsForward(resolve.getParent(), PsiWhiteSpace.class))) {
+                initializer = ((PsiVariable)resolve).getInitializer();
+              }
+              variableName = ((PsiVariable)resolve).getName() + ".";
+            }
+          } else if (qualifierExpression == null) {
+            variableName = "";
+          }
+
+          PsiElement result = null;
+          if (initializer != null) {
+            final PsiType initializerType = initializer.getType();
+            final PsiClassType rawType = initializerType instanceof PsiClassType ? ((PsiClassType)initializerType).rawType() : null;
+            if (rawType != null && rawType.equalsToText(CommonClassNames.JAVA_UTIL_ARRAY_LIST)) {
+              iteration += "toList()";
+            } else if (rawType != null && rawType.equalsToText(CommonClassNames.JAVA_UTIL_HASH_SET)) {
+              iteration += "toSet()";
+            } else {
+              iteration += "toCollection(() -> " + initializer.getText() +")";
+            }
+            iteration += ")";
+            result = initializer.replace(JavaPsiFacade.getElementFactory(project).createExpressionFromText(iteration, foreachStatement));
+            foreachStatement.delete();
+          } else if (variableName != null){
+            iteration += "toList())";
+            result = foreachStatement.replace(JavaPsiFacade.getElementFactory(project).createStatementFromText(variableName + "addAll(" + iteration +");", foreachStatement));
+          }
+
+          if (result != null) {
+            result = JavaCodeStyleManager.getInstance(project).shortenClassReferences(result);
+          }
+        }
+      }
+    }
+  }
+
   public static PsiIfStatement extractIfStatement(PsiStatement body) {
     PsiIfStatement ifStmt = null;
     if (body instanceof PsiIfStatement) {
@@ -201,6 +345,34 @@
         ifStmt = (PsiIfStatement)statements[0];
       }
     }
-    return ifStmt;
+    if (ifStmt != null && ifStmt.getElseBranch() == null && ifStmt.getThenBranch() != null) {
+      return ifStmt;
+    }
+    return null;
+  }
+  
+  private static PsiMethodCallExpression extractAddCall(PsiStatement body) {
+    final PsiIfStatement ifStatement = extractIfStatement(body);
+    if (ifStatement != null) {
+      return extractAddCall(ifStatement.getThenBranch());
+    }
+    PsiExpressionStatement stmt = null;
+    if (body instanceof PsiBlockStatement) {
+      final PsiStatement[] statements = ((PsiBlockStatement)body).getCodeBlock().getStatements();
+      if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
+        stmt = (PsiExpressionStatement)statements[0];
+      }
+    }
+    else if (body instanceof PsiExpressionStatement) {
+      stmt = (PsiExpressionStatement)body;
+    }
+
+    if (stmt != null) {
+      final PsiExpression expression = stmt.getExpression();
+      if (expression instanceof PsiMethodCallExpression) {
+        return (PsiMethodCallExpression)expression;
+      }
+    }
+    return null;
   }
 }
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
index cc1b2ae..2e15ac4 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
@@ -506,12 +506,16 @@
         final String text = isNullLiteralExpression(expr)
                             ? InspectionsBundle.message("dataflow.message.return.null.from.notnullable", presentableNullable)
                             : InspectionsBundle.message("dataflow.message.return.nullable.from.notnullable", presentableNullable);
-        holder.registerProblem(expr, text, new AnnotateMethodFix(defaultNullable, ArrayUtil.toStringArray(manager.getNotNulls())){
-          @Override
-          public int shouldAnnotateBaseMethod(PsiMethod method, PsiMethod superMethod, Project project) {
-            return 1;
-          }
-        });
+        final LocalQuickFix[] fixes =
+          PsiTreeUtil.skipParentsOfType(expr, PsiCodeBlock.class, PsiReturnStatement.class) instanceof PsiLambdaExpression
+          ? LocalQuickFix.EMPTY_ARRAY
+          : new LocalQuickFix[]{ new AnnotateMethodFix(defaultNullable, ArrayUtil.toStringArray(manager.getNotNulls())) {
+            @Override
+            public int shouldAnnotateBaseMethod(PsiMethod method, PsiMethod superMethod, Project project) {
+              return 1;
+            }
+          }};
+        holder.registerProblem(expr, text, fixes);
       }
     }
   }
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java
index b647e7d..f8c395c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java
@@ -81,6 +81,13 @@
       }
     }
 
+    final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(element);
+    if (interfaceMethod != null) {
+      final Icon icon = AllIcons.Gutter.ImplementingMethod;
+      final MarkerType type = MarkerType.OVERRIDING_METHOD;
+      return new ArrowUpLineMarkerInfo(element, icon, type);
+    }
+
     if (myDaemonSettings.SHOW_METHOD_SEPARATORS && element.getFirstChild() == null) {
       PsiElement element1 = element;
       boolean isMember = false;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java
index 12b1788..72e8eca 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java
@@ -53,27 +53,27 @@
   public static final MarkerType OVERRIDING_METHOD = new MarkerType(new NullableFunction<PsiElement, String>() {
     @Override
     public String fun(PsiElement element) {
-      PsiElement parent = element.getParent();
+      PsiElement parent = getParentMethod(element);
       if (!(parent instanceof PsiMethod)) return null;
       PsiMethod method = (PsiMethod)parent;
 
-      return calculateOverridingMethodTooltip(method);
+      return calculateOverridingMethodTooltip(method, method != element.getParent());
     }
   }, new LineMarkerNavigator(){
     @Override
     public void browse(MouseEvent e, PsiElement element) {
-      PsiElement parent = element.getParent();
+      PsiElement parent = getParentMethod(element);
       if (!(parent instanceof PsiMethod)) return;
       PsiMethod method = (PsiMethod)parent;
-      navigateToOverridingMethod(e, method);
+      navigateToOverridingMethod(e, method, method != element.getParent());
 
     }
   });
 
   @Nullable
-  public static String calculateOverridingMethodTooltip(PsiMethod method) {
-    PsiMethod[] superMethods = method.findSuperMethods(false);
-    if (superMethods.length == 0) return null;
+  public static String calculateOverridingMethodTooltip(PsiMethod method, boolean acceptSelf) {
+    PsiMethod[] superMethods = composeSuperMethods(method, acceptSelf);
+    if (superMethods == null) return null;
 
     PsiMethod superMethod = superMethods[0];
     boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT);
@@ -90,9 +90,9 @@
     return GutterIconTooltipHelper.composeText(superMethods, "", DaemonBundle.message(key));
   }
 
-  public static void navigateToOverridingMethod(MouseEvent e, PsiMethod method) {
-    PsiMethod[] superMethods = method.findSuperMethods(false);
-    if (superMethods.length == 0) return;
+  public static void navigateToOverridingMethod(MouseEvent e, PsiMethod method, boolean acceptSelf) {
+    PsiMethod[] superMethods = composeSuperMethods(method, acceptSelf);
+    if (superMethods == null) return;
     boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(superMethods);
     PsiElementListNavigator.openTargets(e, superMethods,
                                         DaemonBundle.message("navigation.title.super.method", method.getName()),
@@ -100,6 +100,22 @@
                                         new MethodCellRenderer(showMethodNames));
   }
 
+  @Nullable
+  private static PsiMethod[] composeSuperMethods(PsiMethod method, boolean acceptSelf) {
+    PsiMethod[] superMethods = method.findSuperMethods(false);
+    if (acceptSelf) {
+      superMethods = ArrayUtil.prepend(method, superMethods);
+    }
+    if (superMethods.length == 0) return null;
+    return superMethods;
+  }
+
+  private static PsiElement getParentMethod(PsiElement element) {
+    final PsiElement parent = element.getParent();
+    final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(element);
+    return interfaceMethod != null ? interfaceMethod : parent;
+  }
+
   public static final String SEARCHING_FOR_OVERRIDING_METHODS = "Searching for overriding methods";
   public static final MarkerType OVERRIDEN_METHOD = new MarkerType(new NullableFunction<PsiElement, String>() {
     @Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToCatchFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToCatchFix.java
index ccb1c3c..5d51949 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToCatchFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToCatchFix.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -52,7 +52,9 @@
     PsiDocumentManager.getInstance(project).commitAllDocuments();
 
     PsiElement element = findElement(file, offset);
-    PsiTryStatement tryStatement = (PsiTryStatement) element.getParent();
+    if (element == null) return;
+
+    PsiTryStatement tryStatement = (PsiTryStatement)element.getParent();
     List<PsiClassType> unhandledExceptions = new ArrayList<PsiClassType>(ExceptionUtil.collectUnhandledExceptions(element, null));
     ExceptionUtil.sortExceptionsByHierarchy(unhandledExceptions);
 
@@ -86,7 +88,9 @@
     }
   }
 
-  private static PsiCodeBlock addCatchStatement(PsiTryStatement tryStatement, PsiClassType exceptionType, PsiFile file) throws IncorrectOperationException {
+  private static PsiCodeBlock addCatchStatement(PsiTryStatement tryStatement,
+                                                PsiClassType exceptionType,
+                                                PsiFile file) throws IncorrectOperationException {
     PsiElementFactory factory = JavaPsiFacade.getInstance(tryStatement.getProject()).getElementFactory();
 
     if (tryStatement.getTryBlock() == null) {
@@ -108,9 +112,12 @@
     }
 
     PsiParameter[] parameters = tryStatement.getCatchBlockParameters();
-    parameters[parameters.length - 1].getTypeElement().replace(factory.createTypeElement(exceptionType));
-    PsiCodeBlock[] catchBlocks = tryStatement.getCatchBlocks();
+    PsiTypeElement typeElement = parameters[parameters.length - 1].getTypeElement();
+    if (typeElement != null) {
+      JavaCodeStyleManager.getInstance(file.getProject()).shortenClassReferences(typeElement);
+    }
 
+    PsiCodeBlock[] catchBlocks = tryStatement.getCatchBlocks();
     return catchBlocks[catchBlocks.length - 1];
   }
 
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java
index 19a4639..69800e5 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java
@@ -200,7 +200,7 @@
             //do not show methods from default package
             && !((PsiJavaFile)file).getPackageName().isEmpty()
             && PsiUtil.isAccessible(file.getProject(), method, element, containingClass)) {
-          if (method.isDeprecated()) {
+          if (isEffectivelyDeprecated(method)) {
             deprecated.put(containingClass, method);
             return processCondition();
           }
@@ -209,6 +209,20 @@
         return processCondition();
       }
 
+      private boolean isEffectivelyDeprecated(PsiMethod method) {
+        if (method.isDeprecated()) {
+          return true;
+        }
+        PsiClass aClass = method.getContainingClass();
+        while (aClass != null) {
+          if (aClass.isDeprecated()) {
+            return true;
+          }
+          aClass = aClass.getContainingClass();
+        }
+        return false;
+      }
+
       private boolean processCondition() {
         return (applicableList.isEmpty() ? list : applicableList).size() + deprecated.size() < 50;
       }
diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/AnnotationParameterInfoHandler.java b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/AnnotationParameterInfoHandler.java
index e727568..0d822fe 100644
--- a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/AnnotationParameterInfoHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/AnnotationParameterInfoHandler.java
@@ -21,7 +21,6 @@
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.text.CharArrayUtil;
-import com.intellij.xml.util.XmlStringUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -119,9 +118,9 @@
     @NonNls StringBuilder buffer = new StringBuilder();
     buffer.append(p.getReturnType().getPresentableText());
     buffer.append(" ");
-    int highlightStartOffset = XmlStringUtil.escapeString(buffer.toString()).length();
+    int highlightStartOffset = buffer.length();
     buffer.append(p.getName());
-    int highlightEndOffset = XmlStringUtil.escapeString(buffer.toString()).length();
+    int highlightEndOffset = buffer.length();
     buffer.append("()");
 
     if (p.getDefaultValue() != null) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java
index 5da27d9..b3918fd 100644
--- a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java
@@ -32,7 +32,6 @@
 import com.intellij.psi.util.PsiUtilBase;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.containers.HashSet;
-import com.intellij.xml.util.XmlStringUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -393,7 +392,7 @@
       for (int j = 0; j < numParams; j++) {
         PsiParameter param = parms[j];
 
-        int startOffset = XmlStringUtil.escapeString(buffer.toString()).length();
+        int startOffset = buffer.length();
 
         if (param.isValid()) {
           PsiType paramType = param.getType();
@@ -411,7 +410,7 @@
           }
         }
 
-        int endOffset = XmlStringUtil.escapeString(buffer.toString()).length();
+        int endOffset = buffer.length();
 
         if (j < numParams - 1) {
           buffer.append(", ");
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddAnnotationIntention.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddAnnotationIntention.java
index 2b839b5..daf5aa5 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddAnnotationIntention.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddAnnotationIntention.java
@@ -26,13 +26,11 @@
 import com.intellij.codeInsight.CodeInsightBundle;
 import com.intellij.codeInsight.intention.AddAnnotationFix;
 import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
-import com.intellij.openapi.editor.CaretModel;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Pair;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 
@@ -49,22 +47,11 @@
   // include not in project files
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
-    CaretModel caretModel = editor.getCaretModel();
-    int position = caretModel.getOffset();
-    PsiElement element = file.findElementAt(position);
-    return element != null && isAvailable(project, element);
-  }
-
-  public boolean isAvailable(@NotNull final Project project, @NotNull final PsiElement element) {
-    if (!element.isValid()) return false;
-    final PsiModifierListOwner owner;
-    if (!element.getManager().isInProject(element) || CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS) {
-      owner = AddAnnotationPsiFix.getContainer(element);
-    }
-    else {
+    final PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(file, editor.getCaretModel().getOffset());
+    if (owner == null ||
+        owner.getManager().isInProject(owner) && !CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS) {
       return false;
     }
-    if (owner == null) return false;
     Pair<String, String[]> annotations = getAnnotations(project);
     String toAdd = annotations.first;
     String[] toRemove = annotations.second;
@@ -82,11 +69,7 @@
 
   @Override
   public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
-    CaretModel caretModel = editor.getCaretModel();
-    int position = caretModel.getOffset();
-    PsiElement element = file.findElementAt(position);
-
-    PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(element);
+    PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(file, editor.getCaretModel().getOffset());
     if (owner == null || !owner.isValid()) return;
     Pair<String, String[]> annotations = getAnnotations(project);
     String toAdd = annotations.first;
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseColorIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseColorIntentionAction.java
index adde45b..f3c9df9 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseColorIntentionAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseColorIntentionAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,9 +28,11 @@
 
 /**
  * @author Danila Ponomarenko
+ * @author Konstantin Bulenkov
  */
 public abstract class BaseColorIntentionAction extends PsiElementBaseIntentionAction implements HighPriorityAction {
   protected static final String JAVA_AWT_COLOR = "java.awt.Color";
+  protected static final String COLOR_UI_RESOURCE = "javax.swing.plaf.ColorUIResource";
 
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
@@ -39,29 +41,28 @@
     }
 
     final PsiNewExpression expression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class, false);
-    if (expression == null) {
-      return false;
-    }
-
-    return isJavaAwtColor(expression.getClassOrAnonymousClassReference()) && isValueArguments(expression.getArgumentList());
+    return expression != null
+           && isJavaAwtColor(expression.getClassOrAnonymousClassReference())
+           && isValueArguments(expression.getArgumentList());
   }
 
   private static boolean isJavaAwtColor(@Nullable PsiJavaCodeReferenceElement ref) {
-    if (ref == null) {
-      return false;
-    }
+    final String fqn = getFqn(ref);
+    return JAVA_AWT_COLOR.equals(fqn) || COLOR_UI_RESOURCE.equals(fqn);
+  }
 
-    final PsiReference reference = ref.getReference();
-    if (reference == null) {
-      return false;
+  @Nullable
+  protected static String getFqn(@Nullable PsiJavaCodeReferenceElement ref) {
+    if (ref != null) {
+      final PsiReference reference = ref.getReference();
+      if (reference != null) {
+        final PsiElement psiElement = reference.resolve();
+        if (psiElement instanceof PsiClass) {
+          return ((PsiClass)psiElement).getQualifiedName();
+        }
+      }
     }
-
-    final PsiElement psiElement = reference.resolve();
-    if (psiElement instanceof PsiClass && JAVA_AWT_COLOR.equals(((PsiClass)psiElement).getQualifiedName())) {
-      return true;
-    }
-
-    return false;
+    return null;
   }
 
   private static boolean isValueArguments(@Nullable PsiExpressionList arguments) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ColorChooserIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ColorChooserIntentionAction.java
index db93d4e..f5d1b3a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ColorChooserIntentionAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ColorChooserIntentionAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -191,7 +191,7 @@
       final PsiManager manager = expression.getManager();
       final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
       final PsiExpression newCall = factory.createExpressionFromText(
-        "new " + JAVA_AWT_COLOR + "("
+        "new " + getFqn(expression.getClassOrAnonymousClassReference()) + "("
         + color.getRed() + ", "
         + color.getGreen() + ", "
         + color.getBlue()
diff --git a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java
index 94ddb7a..55d82a9 100644
--- a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaGotoSuperHandler.java
@@ -30,6 +30,7 @@
 import com.intellij.psi.impl.FindSuperElementsHelper;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.ArrayUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -65,20 +66,27 @@
 
   @Nullable
   private PsiElement[] findSuperElements(PsiFile file, int offset) {
-    PsiNameIdentifierOwner parent = getElement(file, offset);
-    if (parent == null) return null;
+    PsiElement element = getElement(file, offset);
+    if (element == null) return null;
+
+    final PsiExpression expression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class, PsiMethodReferenceExpression.class);
+    if (expression != null) {
+      final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(expression);
+      if (interfaceMethod != null) {
+        return ArrayUtil.prepend(interfaceMethod, interfaceMethod.findSuperMethods(false));
+      }
+    }
+
+    final PsiNameIdentifierOwner parent = PsiTreeUtil.getNonStrictParentOfType(element, PsiMethod.class, PsiClass.class);
+    if (parent == null) {
+      return null;
+    }
 
     return FindSuperElementsHelper.findSuperElements(parent);
   }
 
-  protected PsiNameIdentifierOwner getElement(PsiFile file, int offset) {
-    PsiElement element = file.findElementAt(offset);
-    if (element == null) return null;
-
-    PsiNameIdentifierOwner parent = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiClass.class);
-    if (parent == null)
-      return null;
-    return parent;
+  protected PsiElement getElement(PsiFile file, int offset) {
+    return file.findElementAt(offset);
   }
 
   @Override
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java
index 7040347..767077b 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java
@@ -28,7 +28,6 @@
 import com.intellij.openapi.ui.Messages;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
@@ -48,22 +47,15 @@
 
   @Nullable
   private static PsiMethod getTargetMethod(@NotNull Project project, Editor editor, PsiFile file) {
-    PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
-    if (element == null) return null;
-    if (!element.getManager().isInProject(element) || CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS) {
-      final PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(element);
-      if (owner instanceof PsiMethod) {
-        PsiElement original = owner.getOriginalElement();
-        if (original instanceof PsiMethod) {
-          return (PsiMethod)original;
-        }
-        return (PsiMethod)owner;
-      }
+    final PsiModifierListOwner owner =  AddAnnotationPsiFix.getContainer(file, editor.getCaretModel().getOffset());
+    if (owner instanceof PsiMethod &&
+        (!owner.getManager().isInProject(owner) || CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS)) {
+      PsiElement original = owner.getOriginalElement();
+      return original instanceof PsiMethod ? (PsiMethod)original : (PsiMethod)owner;
     }
     return null;
   }
 
-
   @Override
   public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
     final PsiMethod method = getTargetMethod(project, editor, file);
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java
index db020ad..42d3098 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaReferenceAdjuster.java
@@ -60,6 +60,12 @@
         }
 
         if (rightKind) {
+          // annotations may jump out of reference (see PsiJavaCodeReferenceImpl#setAnnotations()) so they should be processed first
+          List<PsiAnnotation> annotations = PsiTreeUtil.getChildrenOfTypeAsList(ref, PsiAnnotation.class);
+          for (PsiAnnotation annotation : annotations) {
+            process(annotation.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode);
+          }
+
           boolean isInsideDocComment = TreeUtil.findParent(element, JavaDocElementType.DOC_COMMENT) != null;
           boolean isShort = !ref.isQualified();
           if (isInsideDocComment ? !useFqInJavadoc : !useFqInCode) {
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReferenceSet.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReferenceSet.java
index c184775..dbcbfdc 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReferenceSet.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReferenceSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
 import com.intellij.psi.PsiReference;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
@@ -44,27 +45,29 @@
   private final int myStartInElement;
   private final JavaClassReferenceProvider myProvider;
 
-  public JavaClassReferenceSet(String str, PsiElement element, int startInElement, final boolean isStatic, JavaClassReferenceProvider provider) {
+  public JavaClassReferenceSet(@NotNull String str, @NotNull PsiElement element, int startInElement, final boolean isStatic, @NotNull JavaClassReferenceProvider provider) {
     this(str, element, startInElement, isStatic, provider, null);
   }
 
-  private JavaClassReferenceSet(String str, PsiElement element, int startInElement, final boolean isStatic, JavaClassReferenceProvider provider,
+  private JavaClassReferenceSet(@NotNull String str, @NotNull PsiElement element, int startInElement, final boolean isStatic, @NotNull JavaClassReferenceProvider provider,
                         JavaClassReferenceSet context) {
     myStartInElement = startInElement;
     myProvider = provider;
     reparse(str, element, isStatic, context);
   }
 
+  @NotNull
   public JavaClassReferenceProvider getProvider() {
     return myProvider;
   }
 
+  @NotNull
   public TextRange getRangeInElement() {
     PsiReference[] references = getReferences();
     return new TextRange(references[0].getRangeInElement().getStartOffset(), references[references.length - 1].getRangeInElement().getEndOffset());
   }
 
-  private void reparse(String str, PsiElement element, final boolean isStaticImport, JavaClassReferenceSet context) {
+  private void reparse(@NotNull String str, @NotNull PsiElement element, final boolean isStaticImport, JavaClassReferenceSet context) {
     myElement = element;
     myContext = context;
     final List<JavaClassReference> referencesList = new ArrayList<JavaClassReference>();
@@ -186,7 +189,8 @@
     myReferences = referencesList.toArray(new JavaClassReference[referencesList.size()]);
   }
 
-  protected JavaClassReference createReference(final int referenceIndex, final String subreferenceText, final TextRange textRange,
+  @NotNull
+  protected JavaClassReference createReference(final int referenceIndex, @NotNull String subreferenceText, @NotNull TextRange textRange,
                                                final boolean staticImport) {
     return new JavaClassReference(this, textRange, referenceIndex, subreferenceText, staticImport);
   }
@@ -200,7 +204,7 @@
     return isAllowDollarInNames() ? c == DOLLAR : c == DOT;
   }
 
-  public void reparse(PsiElement element, final TextRange range) {
+  public void reparse(@NotNull PsiElement element, @NotNull TextRange range) {
     final String text = range.substring(element.getText());
     reparse(text, element, false, myContext);
   }
@@ -209,6 +213,7 @@
     return myReferences[index];
   }
 
+  @NotNull
   public JavaClassReference[] getAllReferences() {
     JavaClassReference[] result = myReferences;
     if (myNestedGenericParameterReferences != null) {
@@ -229,10 +234,12 @@
     return myProvider.isSoft();
   }
 
+  @NotNull
   public PsiElement getElement() {
     return myElement;
   }
 
+  @NotNull
   public PsiReference[] getReferences() {
     return myReferences;
   }
@@ -243,6 +250,7 @@
   }
 
   @SuppressWarnings({"UnresolvedPropertyKey"})
+  @NotNull
   public String getUnresolvedMessagePattern(int index){
     if (canReferencePackage(index)) {
       return JavaErrorMessages.message("error.cannot.resolve.class.or.package");
diff --git a/java/java-impl/src/com/intellij/refactoring/changeClassSignature/ChangeClassSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeClassSignature/ChangeClassSignatureProcessor.java
index ee207fb..a32dc46 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeClassSignature/ChangeClassSignatureProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeClassSignature/ChangeClassSignatureProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -21,6 +21,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Ref;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.searches.ReferencesSearch;
 import com.intellij.psi.util.PsiUtil;
@@ -187,27 +188,28 @@
     ChangeSignatureUtil.synchronizeList(myClass.getTypeParameterList(), newTypeParameters, TypeParameterList.INSTANCE, toRemoveParms);
   }
 
-  private boolean[] detectRemovedParameters(final PsiTypeParameter[] originaltypeParameters) {
-    final boolean[] toRemoveParms = new boolean[originaltypeParameters.length];
-    Arrays.fill(toRemoveParms, true);
+  private boolean[] detectRemovedParameters(final PsiTypeParameter[] original) {
+    final boolean[] toRemove = new boolean[original.length];
+    Arrays.fill(toRemove, true);
     for (final TypeParameterInfo info : myNewSignature) {
       int oldParameterIndex = info.getOldParameterIndex();
       if (oldParameterIndex >= 0) {
-        toRemoveParms[oldParameterIndex] = false;
+        toRemove[oldParameterIndex] = false;
       }
     }
-    return toRemoveParms;
+    return toRemove;
   }
 
-  private void processUsage(final UsageInfo usage, final PsiTypeParameter[] originalTypeParameters, final boolean[] toRemoveParms)
-    throws IncorrectOperationException {
+  private void processUsage(UsageInfo usage, PsiTypeParameter[] original, boolean[] toRemove) throws IncorrectOperationException {
     PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
     PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement)usage.getElement();
+    assert referenceElement != null : usage;
     PsiSubstitutor usageSubstitutor = determineUsageSubstitutor(referenceElement);
 
     PsiReferenceParameterList referenceParameterList = referenceElement.getParameterList();
+    assert referenceParameterList != null : referenceElement;
     PsiTypeElement[] oldValues = referenceParameterList.getTypeParameterElements();
-    if (oldValues.length != originalTypeParameters.length) return;
+    if (oldValues.length != original.length) return;
     List<PsiTypeElement> newValues = new ArrayList<PsiTypeElement>();
     for (final TypeParameterInfo info : myNewSignature) {
       int oldIndex = info.getOldParameterIndex();
@@ -221,7 +223,9 @@
         newValues.add(newValue);
       }
     }
-    ChangeSignatureUtil.synchronizeList(referenceParameterList, newValues, ReferenceParameterList.INSTANCE, toRemoveParms);
+
+    ChangeSignatureUtil.synchronizeList(referenceParameterList, newValues, ReferenceParameterList.INSTANCE, toRemove);
+    JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(referenceParameterList);
   }
 
   private PsiSubstitutor determineUsageSubstitutor(PsiJavaCodeReferenceElement referenceElement) {
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java
index aa27a6e..69fc990 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -33,11 +33,13 @@
 import java.util.List;
 
 public class ParameterInfoImpl implements JavaParameterInfo {
+  public static final ParameterInfoImpl[] EMPTY_ARRAY = {};
+
   private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ParameterInfoImpl");
+
   public int oldParameterIndex;
-  boolean useAnySingleVariable;
+  private boolean useAnySingleVariable;
   private String name = "";
-  public static final ParameterInfoImpl[] EMPTY_ARRAY = new ParameterInfoImpl[0];
 
   private CanonicalTypes.Type myType;
   String defaultValue = "";
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassProcessor.java
index 25a9481..2b483dd 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -20,6 +20,7 @@
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.wm.WindowManager;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.searches.ReferencesSearch;
 import com.intellij.psi.util.PsiTreeUtil;
@@ -259,9 +260,13 @@
         new InlineToAnonymousConstructorProcessor(myClass, psiNewExpression, superType).run();
       }
       else {
-        PsiJavaCodeReferenceElement element =
-          JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory().createClassReferenceElement(superType.resolve());
-        psiNewExpression.getClassReference().replace(element);        
+        PsiClass target = superType.resolve();
+        assert target != null : superType;
+        PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
+        PsiJavaCodeReferenceElement element = factory.createClassReferenceElement(target);
+        PsiJavaCodeReferenceElement reference = psiNewExpression.getClassReference();
+        assert reference != null : psiNewExpression;
+        reference.replace(element);
       }
     }
     catch (IncorrectOperationException e) {
@@ -276,7 +281,8 @@
     PsiType substType = classResolveResult.getSubstitutor().substitute(superType);
     assert classResolveResult.getElement() == myClass;
     try {
-      typeElement.replace(factory.createTypeElement(substType));
+      PsiElement replaced = typeElement.replace(factory.createTypeElement(substType));
+      JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(replaced);
     }
     catch(IncorrectOperationException e) {
       LOG.error(e);
diff --git a/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/usageInfo/ReplaceWithSubtypeUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/usageInfo/ReplaceWithSubtypeUsageInfo.java
index f2a6a2e..ec1e10d 100644
--- a/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/usageInfo/ReplaceWithSubtypeUsageInfo.java
+++ b/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/usageInfo/ReplaceWithSubtypeUsageInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -13,21 +13,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-/*
- * User: anna
- * Date: 27-Aug-2008
- */
 package com.intellij.refactoring.inlineSuperClass.usageInfo;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.refactoring.util.FixableUsageInfo;
 import com.intellij.util.Function;
 import com.intellij.util.IncorrectOperationException;
 
+/**
+ * @author anna
+ * @since 27-Aug-2008
+ */
 public class ReplaceWithSubtypeUsageInfo extends FixableUsageInfo {
   public static final Logger LOG = Logger.getInstance("#" + ReplaceWithSubtypeUsageInfo.class.getName());
   private final PsiTypeElement myTypeElement;
@@ -51,8 +52,10 @@
 
   public void fixUsage() throws IncorrectOperationException {
     if (myTypeElement.isValid()) {
-      final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(myTypeElement.getProject()).getElementFactory();
-      myTypeElement.replace(elementFactory.createTypeElement(myTargetClassType));
+      Project project = myTypeElement.getProject();
+      PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
+      PsiElement replaced = myTypeElement.replace(elementFactory.createTypeElement(myTargetClassType));
+      JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced);
     }
   }
 
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java
index 6d333e9..3e92a19 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java
@@ -23,6 +23,7 @@
 import com.intellij.history.LocalHistory;
 import com.intellij.history.LocalHistoryAction;
 import com.intellij.ide.util.DirectoryChooser;
+import com.intellij.ide.util.PlatformPackageUtil;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.command.CommandProcessor;
 import com.intellij.openapi.diagnostic.Logger;
@@ -266,7 +267,8 @@
       return aPackage != null ? getTargetPackageNameForMovedElement(aPackage) : "";
     }
     else if (psiElement != null) {
-      PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(psiElement.getContainingFile().getContainingDirectory());
+      PsiDirectory directory = PlatformPackageUtil.getDirectory(psiElement);
+      PsiPackage aPackage = directory == null ? null : JavaDirectoryService.getInstance().getPackage(directory);
       return aPackage != null ? aPackage.getQualifiedName() : "";
     }
     else {
diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java
index f6cdaba..0004ff4 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -18,6 +18,7 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.impl.PsiDiamondTypeUtil;
 import com.intellij.psi.impl.source.tree.ChildRole;
 import com.intellij.psi.impl.source.tree.CompositeElement;
@@ -109,18 +110,19 @@
       if (!migratedType.isValid()) {
         migratedType = JavaPsiFacade.getElementFactory(project).createTypeByFQClassName(migratedType.getCanonicalText());
       }
-      final PsiTypeElement typeElement =
-          JavaPsiFacade.getInstance(project).getElementFactory().createTypeElement(migratedType);
+      final PsiTypeElement typeElement = JavaPsiFacade.getInstance(project).getElementFactory().createTypeElement(migratedType);
       if (element instanceof PsiMethod) {
         final PsiTypeElement returnTypeElement = ((PsiMethod)element).getReturnTypeElement();
         if (returnTypeElement != null) {
-          returnTypeElement.replace(typeElement);
+          final PsiElement replaced = returnTypeElement.replace(typeElement);
+          JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced);
         }
       }
       else if (element instanceof PsiVariable) {
         final PsiTypeElement varTypeElement = ((PsiVariable)element).getTypeElement();
         if (varTypeElement != null) {
-          varTypeElement.replace(typeElement);
+          final PsiElement replaced = varTypeElement.replace(typeElement);
+          JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced);
         }
       }
       else {
diff --git a/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java b/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java
index 04c48bc..966a7a3 100644
--- a/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java
+++ b/java/java-impl/src/com/intellij/spi/SPIGotoSuperHandler.java
@@ -16,9 +16,8 @@
 package com.intellij.spi;
 
 import com.intellij.codeInsight.navigation.JavaGotoSuperHandler;
-import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiNameIdentifierOwner;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.spi.psi.SPIClassProviderReferenceElement;
 
@@ -27,11 +26,11 @@
  */
 public class SPIGotoSuperHandler extends JavaGotoSuperHandler {
   @Override
-  protected PsiNameIdentifierOwner getElement(PsiFile file, int offset) {
+  protected PsiElement getElement(PsiFile file, int offset) {
     final SPIClassProviderReferenceElement
-      providerElement = PsiTreeUtil.getParentOfType(file.findElementAt(offset), SPIClassProviderReferenceElement.class);
+      providerElement = PsiTreeUtil.getParentOfType(super.getElement(file, offset), SPIClassProviderReferenceElement.class);
     if (providerElement != null) {
-      return (PsiClass)providerElement.resolve();
+      return providerElement.resolve();
     }
 
     return null;
diff --git a/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java b/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java
index 877d274..254dc03 100644
--- a/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.java
+++ b/java/java-impl/src/com/intellij/util/xml/CanonicalPsiTypeConverterImpl.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.
@@ -80,7 +80,8 @@
     final boolean isPrimitiveType = type instanceof PsiPrimitiveType;
 
     return new JavaClassReferenceSet(trimmed, element, offset, false, CLASS_REFERENCE_PROVIDER) {
-      protected JavaClassReference createReference(int refIndex, String subRefText, TextRange textRange, boolean staticImport) {
+      @NotNull
+      protected JavaClassReference createReference(int refIndex, @NotNull String subRefText, @NotNull TextRange textRange, boolean staticImport) {
         return new JavaClassReference(this, textRange, refIndex, subRefText, staticImport) {
           public boolean isSoft() {
             return true;
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java
index 59c7d65..b25f8c5 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.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.
@@ -20,6 +20,7 @@
 package com.intellij.psi.impl.search;
 
 import com.intellij.ide.highlighter.JavaClassFileType;
+import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.roots.JdkOrderEntry;
 import com.intellij.openapi.roots.OrderEntry;
@@ -30,13 +31,25 @@
 import com.intellij.psi.search.DelegatingGlobalSearchScope;
 import com.intellij.psi.search.GlobalSearchScope;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class JavaSourceFilterScope extends DelegatingGlobalSearchScope {
+  private static final Logger LOG = Logger.getInstance(JavaSourceFilterScope.class);
+
+  @Nullable
   private final ProjectFileIndex myIndex;
 
   public JavaSourceFilterScope(@NotNull final GlobalSearchScope delegate) {
     super(delegate);
-    myIndex = ProjectRootManager.getInstance(getProject()).getFileIndex();
+
+    Project project = getProject();
+    if (project != null) {
+      myIndex = ProjectRootManager.getInstance(project).getFileIndex();
+    }
+    else {
+      myIndex = null;
+      LOG.error("delegate.getProject() == null, delegate.getClass() == " + delegate.getClass());
+    }
   }
 
   @Override
@@ -45,6 +58,10 @@
       return false;
     }
 
+    if (myIndex == null) {
+      return false;
+    }
+
     if (JavaClassFileType.INSTANCE == file.getFileType()) {
       return myIndex.isInLibraryClasses(file);
     }
diff --git a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
index 8c36cfa..577d38a 100644
--- a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
@@ -519,6 +519,14 @@
     else if (type instanceof PsiArrayType) {
       return checkNotAssignable(bound, type, true);
     }
+    else if (type instanceof PsiIntersectionType) {
+      for (PsiType psiType : ((PsiIntersectionType)type).getConjuncts()) {
+        if (!checkNotInBounds(psiType, bound, uncheckedConversionByDefault)) {
+          return false; 
+        }
+      }
+      return true;
+    }
     return false;
   }
 
diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
index 15b3208..54bd024 100644
--- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
@@ -60,6 +60,16 @@
     return getFunctionalInterfaceMethod(PsiUtil.resolveGenericsClassInType(functionalInterfaceType));
   }
 
+  public static PsiMethod getFunctionalInterfaceMethod(@Nullable PsiElement element) {
+    if (element instanceof PsiLambdaExpression || element instanceof PsiMethodReferenceExpression) {
+      final PsiType samType = element instanceof PsiLambdaExpression
+                              ? ((PsiLambdaExpression)element).getFunctionalInterfaceType()
+                              : ((PsiMethodReferenceExpression)element).getFunctionalInterfaceType();
+      return getFunctionalInterfaceMethod(samType);
+    }
+    return null;
+  }
+
   @Nullable
   public static PsiMethod getFunctionalInterfaceMethod(PsiClassType.ClassResolveResult result) {
     final PsiClass psiClass = result.getElement();
@@ -308,7 +318,7 @@
               final int finalLambdaIdx = adjustLambdaIdx(lambdaIdx, (PsiMethod)resolve, parameters);
               if (finalLambdaIdx < parameters.length) {
                 if (!tryToSubstitute) return getNormalizedType(parameters[finalLambdaIdx]);
-                return PsiResolveHelper.ourGuard.doPreventingRecursion(expression, true, new Computable<PsiType>() {
+                return PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, true, new Computable<PsiType>() {
                   @Override
                   public PsiType compute() {
                     return resolveResult.getSubstitutor().substitute(getNormalizedType(parameters[finalLambdaIdx]));
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java b/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java
index bc61565..47bd7be 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiArrayType.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.
@@ -16,7 +16,6 @@
 package com.intellij.psi;
 
 import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.openapi.util.text.StringUtil;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -24,7 +23,7 @@
  *
  * @author max
  */
-public class PsiArrayType extends PsiType {
+public class PsiArrayType extends PsiType.Stub {
   private final PsiType myComponentType;
 
   /**
@@ -44,19 +43,33 @@
   @NotNull
   @Override
   public String getPresentableText() {
-    return StringUtil.join(myComponentType.getPresentableText(), getAnnotationsTextPrefix(false, true, true), "[]");
+    return getText(myComponentType.getPresentableText(), "[]", false, true);
   }
 
   @NotNull
   @Override
-  public String getCanonicalText() {
-    return StringUtil.join(myComponentType.getCanonicalText(), "[]");
+  public String getCanonicalText(boolean annotated) {
+    return getText(myComponentType.getCanonicalText(annotated), "[]", true, annotated);
   }
 
   @NotNull
   @Override
   public String getInternalCanonicalText() {
-    return StringUtil.join(myComponentType.getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "[]");
+    return getText(myComponentType.getInternalCanonicalText(), "[]", true, true);
+  }
+
+  protected String getText(@NotNull String prefix, @NotNull String suffix, boolean qualified, boolean annotated) {
+    StringBuilder sb = new StringBuilder(prefix.length() + suffix.length());
+    sb.append(prefix);
+    if (annotated) {
+      PsiAnnotation[] annotations = getAnnotations();
+      if (annotations.length != 0) {
+        sb.append(' ');
+        PsiNameHelper.appendAnnotations(sb, annotations, qualified);
+      }
+    }
+    sb.append(suffix);
+    return sb.toString();
   }
 
   @Override
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java b/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java
index 6de8d02..8130b86 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java
@@ -23,7 +23,7 @@
 /**
  * @author ven
  */
-public class PsiCapturedWildcardType extends PsiType {
+public class PsiCapturedWildcardType extends PsiType.Stub {
   @NotNull private final PsiWildcardType myExistential;
   @NotNull private final PsiElement myContext;
   @Nullable private final PsiTypeParameter myParameter;
@@ -78,8 +78,8 @@
 
   @NotNull
   @Override
-  public String getCanonicalText() {
-    return myExistential.getCanonicalText();
+  public String getCanonicalText(boolean annotated) {
+    return myExistential.getCanonicalText(annotated);
   }
 
   @NotNull
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiClassType.java b/java/java-psi-api/src/com/intellij/psi/PsiClassType.java
index 30d9570..722b9e2 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiClassType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiClassType.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.
@@ -280,4 +280,23 @@
       }
     };
   }
+
+  /**
+   * Temporary class to facilitate transition to {@link #getCanonicalText(boolean)}.
+   */
+  public static abstract class Stub extends PsiClassType {
+    protected Stub(LanguageLevel languageLevel, @NotNull PsiAnnotation[] annotations) {
+      super(languageLevel, annotations);
+    }
+
+    @NotNull
+    @Override
+    public final String getCanonicalText() {
+      return getCanonicalText(false);
+    }
+
+    @NotNull
+    @Override
+    public abstract String getCanonicalText(boolean annotated);
+  }
 }
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiDisjunctionType.java b/java/java-psi-api/src/com/intellij/psi/PsiDisjunctionType.java
index e9e0cf3..1a4062e 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiDisjunctionType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiDisjunctionType.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.
@@ -33,7 +33,7 @@
  * Composite type resulting from Project Coin's multi-catch statements, i.e. <code>FileNotFoundException | EOFException</code>.
  * In most cases should be threatened via its least upper bound (<code>IOException</code> in the example above).
  */
-public class PsiDisjunctionType extends PsiType {
+public class PsiDisjunctionType extends PsiType.Stub {
   private final PsiManager myManager;
   private final List<PsiType> myTypes;
   private final CachedValue<PsiType> myLubCache;
@@ -85,15 +85,21 @@
   @Override
   public String getPresentableText() {
     return StringUtil.join(myTypes, new Function<PsiType, String>() {
-      @Override public String fun(PsiType psiType) { return psiType.getPresentableText(); }
+      @Override
+      public String fun(PsiType psiType) {
+        return psiType.getPresentableText();
+      }
     }, " | ");
   }
 
   @NotNull
   @Override
-  public String getCanonicalText() {
+  public String getCanonicalText(final boolean annotated) {
     return StringUtil.join(myTypes, new Function<PsiType, String>() {
-      @Override public String fun(PsiType psiType) { return psiType.getCanonicalText(); }
+      @Override
+      public String fun(PsiType psiType) {
+        return psiType.getCanonicalText(annotated);
+      }
     }, " | ");
   }
 
@@ -101,7 +107,10 @@
   @Override
   public String getInternalCanonicalText() {
     return StringUtil.join(myTypes, new Function<PsiType, String>() {
-      @Override public String fun(PsiType psiType) { return psiType.getInternalCanonicalText(); }
+      @Override
+      public String fun(PsiType psiType) {
+        return psiType.getInternalCanonicalText();
+      }
     }, " | ");
   }
 
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java b/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java
index 0d14479..085854f 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.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.
@@ -15,7 +15,6 @@
  */
 package com.intellij.psi;
 
-import com.intellij.openapi.util.text.StringUtil;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -45,19 +44,19 @@
   @NotNull
   @Override
   public String getPresentableText() {
-    return StringUtil.join(getComponentType().getPresentableText(), getAnnotationsTextPrefix(false, true, true), "...");
+    return getText(getComponentType().getPresentableText(), "...", false, true);
   }
 
   @NotNull
   @Override
-  public String getCanonicalText() {
-    return StringUtil.join(getComponentType().getCanonicalText(), "...");
+  public String getCanonicalText(boolean annotated) {
+    return getText(getComponentType().getCanonicalText(annotated), "...", true, annotated);
   }
 
   @NotNull
   @Override
   public String getInternalCanonicalText() {
-    return StringUtil.join(getComponentType().getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "...");
+    return getText(getComponentType().getInternalCanonicalText(), "...", true, true);
   }
 
   @Override
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java
index 215bb86..55a5e9d 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.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.
@@ -29,7 +29,7 @@
  *
  * @author ven
  */
-public class PsiIntersectionType extends PsiType {
+public class PsiIntersectionType extends PsiType.Stub {
   private final PsiType[] myConjuncts;
 
   private PsiIntersectionType(@NotNull PsiType[] conjuncts) {
@@ -78,7 +78,8 @@
         for (PsiType existing : array) {
           if (type != existing) {
             final boolean allowUncheckedConversion = type instanceof PsiClassType && ((PsiClassType)type).isRaw();
-            if (TypeConversionUtil.isAssignable(type, existing, allowUncheckedConversion)) {
+            if (TypeConversionUtil.isAssignable(GenericsUtil.eliminateWildcards(type), 
+                                                GenericsUtil.eliminateWildcards(existing), allowUncheckedConversion)) {
               iterator.remove();
               break;
             }
@@ -110,19 +111,19 @@
 
   @NotNull
   @Override
-  public String getCanonicalText() {
-    return myConjuncts[0].getCanonicalText();
+  public String getCanonicalText(boolean annotated) {
+    return myConjuncts[0].getCanonicalText(annotated);
   }
 
   @NotNull
   @Override
   public String getInternalCanonicalText() {
-    StringBuilder buffer = new StringBuilder();
-    for (int i = 0; i < myConjuncts.length; i++) {
-      buffer.append(myConjuncts[i].getInternalCanonicalText());
-      if (i < myConjuncts.length - 1) buffer.append(" & ");
-    }
-    return buffer.toString();
+    return StringUtil.join(myConjuncts, new Function<PsiType, String>() {
+      @Override
+      public String fun(PsiType psiType) {
+        return psiType.getInternalCanonicalText();
+      }
+    }, " & ");
   }
 
   @Override
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiNameHelper.java b/java/java-psi-api/src/com/intellij/psi/PsiNameHelper.java
index 6ae0fa6..6e5e656 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiNameHelper.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiNameHelper.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.
@@ -23,8 +23,11 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.regex.Pattern;
 
+import static com.intellij.util.ObjectUtils.assertNotNull;
 import static com.intellij.util.ObjectUtils.notNull;
 
 /**
@@ -37,7 +40,7 @@
   public static PsiNameHelper getInstance(Project project) {
     return ServiceManager.getService(project, PsiNameHelper.class);
   }
-  
+
   /**
    * Checks if the specified text is a Java identifier, using the language level of the project
    * with which the name helper is associated to filter out keywords.
@@ -121,30 +124,15 @@
   }
 
   @NotNull
-  public static String getPresentableText(@Nullable String refName, @NotNull PsiAnnotation[] annotations, @NotNull PsiType[] typeParameters) {
-    if (typeParameters.length == 0 && annotations.length == 0) {
+  public static String getPresentableText(@Nullable String refName, @NotNull PsiAnnotation[] annotations, @NotNull PsiType[] types) {
+    if (types.length == 0 && annotations.length == 0) {
       return refName != null ? refName : "";
     }
 
     StringBuilder buffer = new StringBuilder();
-
-    if (annotations.length > 0) {
-      for (PsiAnnotation annotation : annotations) {
-        buffer.append(annotation.getText()).append(' ');
-      }
-    }
-
+    appendAnnotations(buffer, annotations, false);
     buffer.append(refName);
-
-    if (typeParameters.length > 0) {
-      buffer.append("<");
-      for (int i = 0; i < typeParameters.length; i++) {
-        buffer.append(typeParameters[i].getPresentableText());
-        if (i < typeParameters.length - 1) buffer.append(", ");
-      }
-      buffer.append(">");
-    }
-
+    appendTypeArgs(buffer, types, false, true);
     return buffer.toString();
   }
 
@@ -262,4 +250,43 @@
     return subpackageName.equals(packageName) ||
            subpackageName.startsWith(packageName) && subpackageName.charAt(packageName.length()) == '.';
   }
+
+  public static void appendTypeArgs(@NotNull StringBuilder sb, @NotNull PsiType[] types, boolean canonical, boolean annotated) {
+    if (types.length == 0) return;
+
+    sb.append('<');
+    for (int i = 0; i < types.length; i++) {
+      if (i > 0) {
+        sb.append(canonical ? "," : ", ");
+      }
+
+      PsiType type = types[i];
+      if (canonical) {
+        sb.append(type.getCanonicalText(annotated));
+      }
+      else {
+        sb.append(type.getPresentableText());
+      }
+    }
+    sb.append('>');
+  }
+
+  public static boolean appendAnnotations(@NotNull StringBuilder sb, @NotNull PsiAnnotation[] annotations, boolean canonical) {
+    return appendAnnotations(sb, Arrays.asList(annotations), canonical);
+  }
+
+  public static boolean appendAnnotations(@NotNull StringBuilder sb, @NotNull List<PsiAnnotation> annotations, boolean canonical) {
+    for (PsiAnnotation annotation : annotations) {
+      sb.append('@');
+      if (canonical) {
+        sb.append(annotation.getQualifiedName());
+        sb.append(annotation.getParameterList().getText());
+      }
+      else {
+        sb.append(assertNotNull(annotation.getNameReferenceElement()).getText());
+      }
+      sb.append(' ');
+    }
+    return annotations.size() > 0;
+  }
 }
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java b/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java
index dd6b0d4..cad6cfd 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java
@@ -30,7 +30,7 @@
 /**
  * Represents primitive types of Java language.
  */
-public class PsiPrimitiveType extends PsiType {
+public class PsiPrimitiveType extends PsiType.Stub {
   private static final Map<String, PsiPrimitiveType> ourQNameToUnboxed = new THashMap<String, PsiPrimitiveType>();
   private static final Map<PsiPrimitiveType, String> ourUnboxedToQName = new THashMap<PsiPrimitiveType, String>();
 
@@ -52,19 +52,29 @@
   @NotNull
   @Override
   public String getPresentableText() {
-    return getAnnotationsTextPrefix(false, false, true) + myName;
+    return getText(false, true);
   }
 
   @NotNull
   @Override
-  public String getCanonicalText() {
-    return myName;
+  public String getCanonicalText(boolean annotated) {
+    return getText(true, annotated);
   }
 
   @NotNull
   @Override
   public String getInternalCanonicalText() {
-    return getAnnotationsTextPrefix(true, false, true) + myName;
+    return getText(true, true);
+  }
+
+  private String getText(boolean qualified, boolean annotated) {
+    PsiAnnotation[] annotations = getAnnotations();
+    if (!annotated || annotations.length == 0) return myName;
+
+    StringBuilder sb = new StringBuilder();
+    PsiNameHelper.appendAnnotations(sb, annotations, qualified);
+    sb.append(myName);
+    return sb.toString();
   }
 
   /**
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiType.java b/java/java-psi-api/src/com/intellij/psi/PsiType.java
index cfbf026..1dd67fb 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiType.java
@@ -84,6 +84,15 @@
    */
   @NonNls
   @NotNull
+  public String getCanonicalText(boolean annotated) {
+    return getCanonicalText();
+  }
+
+  /**
+   * Same as {@code getCanonicalText(false)}.
+   */
+  @NonNls
+  @NotNull
   public abstract String getCanonicalText();
 
   /**
@@ -284,24 +293,15 @@
     return getAnnotations();
   }
 
-  @NotNull
+  /** @deprecated use {@link PsiNameHelper#appendAnnotations(StringBuilder, PsiAnnotation[], boolean)} (to remove in IDEA 14) */
+  @SuppressWarnings("UnusedDeclaration")
   protected String getAnnotationsTextPrefix(boolean qualified, boolean leadingSpace, boolean trailingSpace) {
     PsiAnnotation[] annotations = getAnnotations();
     if (annotations.length == 0) return "";
 
     StringBuilder sb = new StringBuilder();
     if (leadingSpace) sb.append(' ');
-    for (int i = 0; i < annotations.length; i++) {
-      if (i > 0) sb.append(' ');
-      PsiAnnotation annotation = annotations[i];
-      if (qualified) {
-        sb.append('@').append(annotation.getQualifiedName()).append(annotation.getParameterList().getText());
-      }
-      else {
-        sb.append(annotation.getText());
-      }
-    }
-    if (trailingSpace) sb.append(' ');
+    if (PsiNameHelper.appendAnnotations(sb, annotations, qualified) &&!trailingSpace) sb.setLength(sb.length() - 1);
     return sb.toString();
   }
 
@@ -310,4 +310,23 @@
     //noinspection HardCodedStringLiteral
     return "PsiType:" + getPresentableText();
   }
+
+  /**
+   * Temporary class to facilitate transition to {@link #getCanonicalText(boolean)}.
+   */
+  protected static abstract class Stub extends PsiType {
+    protected Stub(@NotNull PsiAnnotation[] annotations) {
+      super(annotations);
+    }
+
+    @NotNull
+    @Override
+    public final String getCanonicalText() {
+      return getCanonicalText(false);
+    }
+
+    @NotNull
+    @Override
+    public abstract String getCanonicalText(boolean annotated);
+  }
 }
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiWildcardType.java b/java/java-psi-api/src/com/intellij/psi/PsiWildcardType.java
index a3dd77a..d651810 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiWildcardType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiWildcardType.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.
@@ -28,7 +28,7 @@
  *
  * @author dsl
  */
-public class PsiWildcardType extends PsiType {
+public class PsiWildcardType extends PsiType.Stub {
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.PsiWildcardType");
 
   private static final Key<PsiWildcardType> UNBOUNDED_WILDCARD = new Key<PsiWildcardType>("UNBOUNDED_WILDCARD");
@@ -83,21 +83,37 @@
   @NotNull
   @Override
   public String getPresentableText() {
-    return getAnnotationsTextPrefix(false, false, true) +
-           (myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getPresentableText());
+    return getText(false, true, myBound == null ? null : myBound.getPresentableText());
   }
 
   @Override
   @NotNull
-  public String getCanonicalText() {
-    return myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getCanonicalText();
+  public String getCanonicalText(boolean annotated) {
+    return getText(true, annotated, myBound == null ? null : myBound.getCanonicalText(annotated));
   }
 
   @NotNull
   @Override
   public String getInternalCanonicalText() {
-    return getAnnotationsTextPrefix(true, false, true) +
-           (myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getInternalCanonicalText());
+    return getText(true, true, myBound == null ? null : myBound.getInternalCanonicalText());
+  }
+
+  private String getText(boolean qualified, boolean annotated, @Nullable String suffix) {
+    PsiAnnotation[] annotations = getAnnotations();
+    if ((!annotated || annotations.length == 0) && suffix == null) return "?";
+
+    StringBuilder sb = new StringBuilder();
+    if (annotated) {
+      PsiNameHelper.appendAnnotations(sb, annotations, qualified);
+    }
+    if (suffix == null) {
+      sb.append('?');
+    }
+    else {
+      sb.append(myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX);
+      sb.append(suffix);
+    }
+    return sb.toString();
   }
 
   @Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
index 0de45be..77fd008 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
@@ -493,6 +493,13 @@
       return PsiUtil.captureToplevelWildcards(type, expression);
     }
 
+    final PsiElement parent = toplevel.getParent();
+    if (parent instanceof PsiExpressionList &&
+        PsiUtil.isLanguageLevel8OrHigher(parent) &&
+        parent.getParent() instanceof PsiCallExpression) {
+      return PsiUtil.captureToplevelWildcards(type, expression);
+    }
+
     final PsiType normalized = doNormalizeWildcardByPosition(type, expression, toplevel);
     LOG.assertTrue(normalized.isValid(), type);
     if (normalized instanceof PsiClassType && !PsiUtil.isAccessedForWriting(toplevel)) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
index 36a725a..369ce91 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
@@ -15,15 +15,18 @@
  */
 package com.intellij.psi.impl.compiled;
 
+import com.intellij.diagnostic.PluginException;
 import com.intellij.ide.caches.FileContent;
 import com.intellij.ide.highlighter.JavaClassFileType;
 import com.intellij.ide.highlighter.JavaFileType;
+import com.intellij.ide.plugins.PluginManagerCore;
 import com.intellij.lang.ASTNode;
 import com.intellij.lang.FileASTNode;
 import com.intellij.lang.java.JavaLanguage;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.extensions.PluginId;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.progress.NonCancelableSection;
 import com.intellij.openapi.progress.ProgressIndicatorProvider;
@@ -35,6 +38,7 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
+import com.intellij.psi.compiled.ClassFileDecompilers;
 import com.intellij.psi.impl.JavaPsiImplementationHelper;
 import com.intellij.psi.impl.PsiFileEx;
 import com.intellij.psi.impl.java.stubs.PsiClassStub;
@@ -324,7 +328,7 @@
             setMirror(mirrorTreeElement);
           }
           catch (InvalidMirrorException e) {
-            LOG.error(file.getPath(), e);
+            LOG.error(file.getPath(), wrapException(e, file));
           }
           finally {
             section.done();
@@ -337,6 +341,18 @@
     return mirrorTreeElement.getPsi();
   }
 
+  private static Exception wrapException(InvalidMirrorException e, VirtualFile file) {
+    ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
+    if (decompiler instanceof ClassFileDecompilers.Light) {
+      PluginId pluginId = PluginManagerCore.getPluginByClassName(decompiler.getClass().getName());
+      if (pluginId != null) {
+        return new PluginException(e, pluginId);
+      }
+    }
+
+    return e;
+  }
+
   @Override
   public PsiFile getDecompiledPsiFile() {
     return (PsiFile)getMirror();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java
index 599f756..16d9712 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java
@@ -17,8 +17,7 @@
 
 import com.intellij.openapi.util.AtomicNotNullLazyValue;
 import com.intellij.openapi.util.NotNullLazyValue;
-import com.intellij.openapi.util.NullableLazyValue;
-import com.intellij.openapi.util.VolatileNullableLazyValue;
+import com.intellij.openapi.util.Ref;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.PsiImplUtil;
 import com.intellij.psi.impl.PsiJavaParserFacadeImpl;
@@ -28,7 +27,6 @@
 import com.intellij.psi.impl.source.tree.TreeElement;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement {
   @NonNls static final char VARIANCE_NONE = '\0';
@@ -41,18 +39,18 @@
   private final PsiElement myParent;
   private final String myTypeText;
   private final char myVariance;
-  private final NullableLazyValue<ClsElementImpl> myChild;
+  private final NotNullLazyValue<Ref<ClsElementImpl>> myChild;
   private final NotNullLazyValue<PsiType> myCachedType;
 
   public ClsTypeElementImpl(@NotNull PsiElement parent, @NotNull String typeText, char variance) {
     myParent = parent;
     myTypeText = TypeInfo.internFrequentType(typeText);
     myVariance = variance;
-    myChild = new VolatileNullableLazyValue<ClsElementImpl>() {
-      @Nullable
+    myChild = new AtomicNotNullLazyValue<Ref<ClsElementImpl>>() {
+      @NotNull
       @Override
-      protected ClsElementImpl compute() {
-        return calculateChild();
+      protected Ref<ClsElementImpl> compute() {
+        return Ref.create(calculateChild());
       }
     };
     myCachedType = new AtomicNotNullLazyValue<PsiType>() {
@@ -67,7 +65,7 @@
   @Override
   @NotNull
   public PsiElement[] getChildren() {
-    ClsElementImpl child = myChild.getValue();
+    ClsElementImpl child = myChild.getValue().get();
     return child != null ? new PsiElement[]{child} : PsiElement.EMPTY_ARRAY;
   }
 
@@ -111,7 +109,7 @@
   public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException {
     setMirrorCheckingType(element, JavaElementType.TYPE);
 
-    ClsElementImpl child = myChild.getValue();
+    ClsElementImpl child = myChild.getValue().get();
     if (child != null) {
       child.setMirror(element.getFirstChildNode());
     }
@@ -157,7 +155,7 @@
     PsiType result = PsiJavaParserFacadeImpl.getPrimitiveType(myTypeText);
     if (result != null) return result;
 
-    ClsElementImpl childElement = myChild.getValue();
+    ClsElementImpl childElement = myChild.getValue().get();
     if (childElement instanceof ClsTypeElementImpl) {
       if (isArray()) {
         switch (myVariance) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java
index a43c02d..f304fe2 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.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.
@@ -30,16 +30,16 @@
 /**
  * @author max
  */
-public class PsiClassReferenceType extends PsiClassType {
+public class PsiClassReferenceType extends PsiClassType.Stub {
   @NotNull
   private final PsiJavaCodeReferenceElement myReference;
 
-  public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel) {
-    this(reference, langLevel, collectAnnotations(reference));
+  public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel level) {
+    this(reference, level, collectAnnotations(reference));
   }
 
-  public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel, @NotNull PsiAnnotation[] annotations) {
-    super(langLevel, annotations);
+  public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel level, @NotNull PsiAnnotation[] annotations) {
+    super(level, annotations);
     myReference = reference;
   }
 
@@ -89,7 +89,7 @@
     return resolveGenerics().getElement();
   }
 
-  private static class DelegatingClassResolveResult implements ClassResolveResult {
+  private static class DelegatingClassResolveResult implements PsiClassType.ClassResolveResult {
     private final JavaResolveResult myDelegate;
 
     private DelegatingClassResolveResult(@NotNull JavaResolveResult delegate) {
@@ -182,19 +182,37 @@
   @NotNull
   @Override
   public String getPresentableText() {
-    return getAnnotationsTextPrefix(false, false, true) + PsiNameHelper.getPresentableText(myReference);
+    String presentableText = PsiNameHelper.getPresentableText(myReference);
+    PsiAnnotation[] annotations = getAnnotations();
+    if (annotations.length == 0) return presentableText;
+
+    StringBuilder sb = new StringBuilder();
+    PsiNameHelper.appendAnnotations(sb, annotations, false);
+    sb.append(presentableText);
+    return sb.toString();
   }
 
   @NotNull
   @Override
-  public String getCanonicalText() {
-    return myReference.getCanonicalText();
+  public String getCanonicalText(boolean annotated) {
+    return getText(annotated);
   }
 
   @NotNull
   @Override
   public String getInternalCanonicalText() {
-    return getAnnotationsTextPrefix(true, false, true) + getCanonicalText();
+    return getText(true);
+  }
+
+  private String getText(boolean annotated) {
+    if (myReference instanceof PsiJavaCodeReferenceElementImpl) {
+      PsiAnnotation[] annotations = getAnnotations();
+      if (!annotated || annotations.length == 0) annotations = null;
+      return ((PsiJavaCodeReferenceElementImpl)myReference).getCanonicalText(annotated, annotations);
+    }
+    else {
+      return myReference.getCanonicalText();
+    }
   }
 
   @NotNull
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java
index 9456c29..77a4501 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.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.
@@ -15,6 +15,7 @@
  */
 package com.intellij.psi.impl.source;
 
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -30,11 +31,12 @@
 /**
  *  @author dsl
  */
-public class PsiImmediateClassType extends PsiClassType {
+public class PsiImmediateClassType extends PsiClassType.Stub {
   private final PsiClass myClass;
   private final PsiSubstitutor mySubstitutor;
   private final PsiManager myManager;
   private String myCanonicalText;
+  private String myCanonicalTextAnnotated;
   private String myPresentableText;
   private String myInternalCanonicalText;
 
@@ -80,15 +82,15 @@
     this(aClass, substitutor, null, PsiAnnotation.EMPTY_ARRAY);
   }
 
-  public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel) {
-    this(aClass, substitutor, languageLevel, PsiAnnotation.EMPTY_ARRAY);
+  public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel level) {
+    this(aClass, substitutor, level, PsiAnnotation.EMPTY_ARRAY);
   }
 
   public PsiImmediateClassType(@NotNull PsiClass aClass,
                                @NotNull PsiSubstitutor substitutor,
-                               @Nullable LanguageLevel languageLevel,
-                               @NotNull PsiAnnotation[] annotations) {
-    super(languageLevel, annotations);
+                               @Nullable LanguageLevel level,
+                               @NotNull PsiAnnotation... annotations) {
+    super(level, annotations);
     myClass = aClass;
     myManager = aClass.getManager();
     mySubstitutor = substitutor;
@@ -138,112 +140,119 @@
   @Override
   public String getPresentableText() {
     if (myPresentableText == null) {
-      StringBuilder buffer = new StringBuilder();
-      buildText(myClass, mySubstitutor, buffer, false, false);
-      myPresentableText = buffer.toString();
+      myPresentableText = getText(TextType.PRESENTABLE, true);
     }
     return myPresentableText;
   }
 
   @NotNull
   @Override
-  public String getCanonicalText() {
-    if (myCanonicalText == null) {
-      assert mySubstitutor.isValid();
-      StringBuilder buffer = new StringBuilder();
-      buildText(myClass, mySubstitutor, buffer, true, false);
-      myCanonicalText = buffer.toString();
+  public String getCanonicalText(boolean annotated) {
+    String cached = annotated ? myCanonicalTextAnnotated : myCanonicalText;
+    if (cached == null) {
+      cached = getText(TextType.CANONICAL, annotated);
+      if (annotated) myCanonicalTextAnnotated = cached;
+      else myCanonicalText = cached;
     }
-    return myCanonicalText;
+    return cached;
   }
 
   @NotNull
   @Override
   public String getInternalCanonicalText() {
     if (myInternalCanonicalText == null) {
-      StringBuilder buffer = new StringBuilder();
-      buildText(myClass, mySubstitutor, buffer, true, true);
-      myInternalCanonicalText = buffer.toString();
+      myInternalCanonicalText = getText(TextType.INT_CANONICAL, true);
     }
     return myInternalCanonicalText;
   }
 
+  private enum TextType { PRESENTABLE, CANONICAL, INT_CANONICAL }
+
+  private String getText(@NotNull TextType textType, boolean annotated) {
+    assert mySubstitutor.isValid();
+    StringBuilder buffer = new StringBuilder();
+    buildText(myClass, mySubstitutor, buffer, textType, annotated);
+    return buffer.toString();
+  }
+
   private void buildText(@NotNull PsiClass aClass,
                          @NotNull PsiSubstitutor substitutor,
                          @NotNull StringBuilder buffer,
-                         boolean canonical,
-                         boolean internal) {
+                         @NotNull TextType textType,
+                         boolean annotated) {
     if (aClass instanceof PsiAnonymousClass) {
-      ClassResolveResult baseResolveResult = ((PsiAnonymousClass) aClass).getBaseClassType().resolveGenerics();
+      ClassResolveResult baseResolveResult = ((PsiAnonymousClass)aClass).getBaseClassType().resolveGenerics();
       PsiClass baseClass = baseResolveResult.getElement();
-      PsiSubstitutor baseSub = baseResolveResult.getSubstitutor();
       if (baseClass != null) {
-        buildText(baseClass, baseSub, buffer, canonical, internal);
+        buildText(baseClass, baseResolveResult.getSubstitutor(), buffer, textType, false);
       }
       return;
     }
 
-    if (canonical == internal) {
-      buffer.append(getAnnotationsTextPrefix(internal, false, true));
-    }
+    boolean qualified = textType != TextType.PRESENTABLE;
 
     PsiClass enclosingClass = null;
     if (!aClass.hasModifierProperty(PsiModifier.STATIC)) {
-      final PsiElement parent = aClass.getParent();
+      PsiElement parent = aClass.getParent();
       if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass)) {
         enclosingClass = (PsiClass)parent;
       }
     }
     if (enclosingClass != null) {
-      buildText(enclosingClass, substitutor, buffer, canonical, false);
+      buildText(enclosingClass, substitutor, buffer, textType, false);
       buffer.append('.');
-      buffer.append(aClass.getName());
     }
-    else {
-      final String name;
-      if (!canonical) {
-        name = aClass.getName();
-      }
-      else {
-        final String qualifiedName = aClass.getQualifiedName();
-        if (qualifiedName == null) {
-          name = aClass.getName();
-        }
-        else {
-          name = qualifiedName;
+    else if (qualified) {
+      String fqn = aClass.getQualifiedName();
+      if (fqn != null) {
+        String prefix = StringUtil.getPackageName(fqn);
+        if (!StringUtil.isEmpty(prefix)) {
+          buffer.append(prefix);
+          buffer.append('.');
         }
       }
-      buffer.append(name);
     }
 
+    if (annotated) {
+      PsiNameHelper.appendAnnotations(buffer, getAnnotations(), qualified);
+    }
+
+    buffer.append(aClass.getName());
+
     PsiTypeParameter[] typeParameters = aClass.getTypeParameters();
     if (typeParameters.length > 0) {
-      StringBuilder pineBuffer = new StringBuilder();
-      pineBuffer.append('<');
+      int pos = buffer.length();
+      buffer.append('<');
+
       for (int i = 0; i < typeParameters.length; i++) {
         PsiTypeParameter typeParameter = typeParameters[i];
         PsiUtilCore.ensureValid(typeParameter);
-        if (i > 0) pineBuffer.append(',');
-        final PsiType substitutionResult = substitutor.substitute(typeParameter);
+
+        if (i > 0) {
+          buffer.append(',');
+          if (textType == TextType.PRESENTABLE) buffer.append(' ');
+        }
+
+        PsiType substitutionResult = substitutor.substitute(typeParameter);
         if (substitutionResult == null) {
-          pineBuffer = null;
+          buffer.setLength(pos);
+          pos = -1;
           break;
         }
         PsiUtil.ensureValidType(substitutionResult);
-        if (canonical) {
-          if (internal) {
-            pineBuffer.append(substitutionResult.getInternalCanonicalText());
-          }
-          else {
-            pineBuffer.append(substitutionResult.getCanonicalText());
-          }
+
+        if (textType == TextType.PRESENTABLE) {
+          buffer.append(substitutionResult.getPresentableText());
+        }
+        else if (textType == TextType.CANONICAL) {
+          buffer.append(substitutionResult.getCanonicalText(annotated));
         }
         else {
-          pineBuffer.append(substitutionResult.getPresentableText());
+          buffer.append(substitutionResult.getInternalCanonicalText());
         }
       }
-      if (pineBuffer != null) {
-        buffer.append(pineBuffer);
+
+      if (pos >= 0) {
         buffer.append('>');
       }
     }
@@ -265,7 +274,6 @@
       return false;
     }
     return equals(patternType);
-
   }
 
   @Override
@@ -277,14 +285,12 @@
   @Override
   @NotNull
   public LanguageLevel getLanguageLevel() {
-    if (myLanguageLevel != null) return myLanguageLevel;
-    return PsiUtil.getLanguageLevel(myClass);
+    return myLanguageLevel != null ? myLanguageLevel : PsiUtil.getLanguageLevel(myClass);
   }
 
   @NotNull
   @Override
-  public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) {
-    if (languageLevel.equals(myLanguageLevel)) return this;
-    return new PsiImmediateClassType(myClass, mySubstitutor, languageLevel,getAnnotations());
+  public PsiClassType setLanguageLevel(@NotNull LanguageLevel level) {
+    return level.equals(myLanguageLevel) ? this : new PsiImmediateClassType(myClass, mySubstitutor, level, getAnnotations());
   }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
index 396b750..5ee1243 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.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.
@@ -49,6 +49,7 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Arrays;
 import java.util.List;
 
 public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement implements PsiJavaCodeReferenceElement, SourceJavaCodeReference {
@@ -255,36 +256,47 @@
   @Override
   @NotNull
   public String getCanonicalText() {
+    return getCanonicalText(false, null);
+  }
+
+  @NotNull
+  public String getCanonicalText(boolean annotated, @Nullable PsiAnnotation[] annotations) {
     switch (getKind()) {
       case CLASS_NAME_KIND:
       case CLASS_OR_PACKAGE_NAME_KIND:
       case CLASS_IN_QUALIFIED_NEW_KIND:
         final PsiElement target = resolve();
         if (target instanceof PsiClass) {
-          final PsiClass aClass = (PsiClass)target;
-          String name = aClass.getQualifiedName();
-          if (name == null) {
-            name = aClass.getName(); //?
+          PsiClass aClass = (PsiClass)target;
+          StringBuilder buffer = new StringBuilder();
+
+          PsiElement qualifier = getQualifier();
+          String prefix = null;
+          if (qualifier instanceof PsiJavaCodeReferenceElementImpl) {
+            prefix = ((PsiJavaCodeReferenceElementImpl)qualifier).getCanonicalText(annotated, null);
           }
-          final PsiType[] types = getTypeParameters();
-          if (types.length == 0) {
-            final PsiElement qualifier = getQualifier();
-            if (qualifier instanceof PsiJavaCodeReferenceElement) {
-              return StringUtil.getQualifiedName(((PsiJavaCodeReferenceElement)qualifier).getCanonicalText(), aClass.getName());
+          else {
+            String fqn = aClass.getQualifiedName();
+            if (fqn != null) {
+              prefix = StringUtil.getPackageName(fqn);
             }
-            return name;
           }
 
-          final StringBuilder buf = new StringBuilder();
-          buf.append(name);
-          buf.append('<');
-          for (int i = 0; i < types.length; i++) {
-            if (i > 0) buf.append(',');
-            buf.append(types[i].getCanonicalText());
+          if (!StringUtil.isEmpty(prefix)) {
+            buffer.append(prefix);
+            buffer.append('.');
           }
-          buf.append('>');
 
-          return buf.toString();
+          if (annotated) {
+            List<PsiAnnotation> list = annotations != null ? Arrays.asList(annotations) : getAnnotations();
+            PsiNameHelper.appendAnnotations(buffer, list, true);
+          }
+
+          buffer.append(aClass.getName());
+
+          PsiNameHelper.appendTypeArgs(buffer, getTypeParameters(), true, annotated);
+
+          return buffer.toString();
         }
         else if (target instanceof PsiPackage) {
           return ((PsiPackage)target).getQualifiedName();
@@ -293,6 +305,7 @@
           LOG.assertTrue(target == null, target);
           return getNormalizedText();
         }
+
       case PACKAGE_NAME_KIND:
       case CLASS_FQ_NAME_KIND:
       case CLASS_FQ_OR_PACKAGE_NAME_KIND:
@@ -327,7 +340,7 @@
 
       if (incompleteCode && result.length == 0 && kind != CLASS_FQ_NAME_KIND && kind != CLASS_FQ_OR_PACKAGE_NAME_KIND) {
         VariableResolverProcessor processor = new VariableResolverProcessor(referenceElement, containingFile);
-        PsiScopesUtil.resolveAndWalk(processor, referenceElement, null, incompleteCode);
+        PsiScopesUtil.resolveAndWalk(processor, referenceElement, null, true);
         result = processor.getResult();
         if (result.length == 0 && kind == CLASS_NAME_KIND) {
           result = referenceElement.resolve(PACKAGE_NAME_KIND, containingFile);
@@ -457,16 +470,16 @@
       case CLASS_FQ_OR_PACKAGE_NAME_KIND:
       case CLASS_OR_PACKAGE_NAME_KIND: {
         int classKind = kind == CLASS_OR_PACKAGE_NAME_KIND ? CLASS_NAME_KIND : CLASS_FQ_NAME_KIND;
-        JavaResolveResult[] result = resolve(classKind,containingFile);
+        JavaResolveResult[] result = resolve(classKind, containingFile);
 
         if (result.length == 1 && !result[0].isAccessible()) {
-          JavaResolveResult[] packageResult = resolve(PACKAGE_NAME_KIND,containingFile);
+          JavaResolveResult[] packageResult = resolve(PACKAGE_NAME_KIND, containingFile);
           if (packageResult.length != 0) {
             result = packageResult;
           }
         }
         else if (result.length == 0) {
-          result = resolve(PACKAGE_NAME_KIND,containingFile);
+          result = resolve(PACKAGE_NAME_KIND, containingFile);
         }
 
         return result;
@@ -607,7 +620,12 @@
 
     for (PsiAnnotation annotation : annotations) {
       if (annotation.getParent() != newParent) {
-        newParent.addAfter(annotation, anchor);
+        if (anchor != null) {
+          newParent.addAfter(annotation, anchor);
+        }
+        else {
+          newParent.add(annotation);
+        }
         annotation.delete();
       }
     }
@@ -935,7 +953,6 @@
     final PsiReferenceParameterList parameterList = getParameterList();
     if (parameterList == null) return PsiType.EMPTY_ARRAY;
     return parameterList.getTypeArguments();
-
   }
 
   @Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java
index 5b76439..20db589 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java
@@ -225,15 +225,21 @@
     return true;
   }
 
-  public static void substituteResults(@NotNull PsiJavaCodeReferenceElement ref, @NotNull JavaResolveResult[] result) {
+  public static void substituteResults(final @NotNull PsiJavaCodeReferenceElement ref, @NotNull JavaResolveResult[] result) {
     if (result.length > 0 && result[0].getElement() instanceof PsiClass) {
-      PsiType[] parameters = ref.getTypeParameters();
       for (int i = 0; i < result.length; i++) {
-        CandidateInfo resolveResult = (CandidateInfo)result[i];
-        PsiElement resultElement = resolveResult.getElement();
+        final CandidateInfo resolveResult = (CandidateInfo)result[i];
+        final PsiElement resultElement = resolveResult.getElement();
         if (resultElement instanceof PsiClass && ((PsiClass)resultElement).hasTypeParameters()) {
-          PsiSubstitutor substitutor = resolveResult.getSubstitutor().putAll((PsiClass)resultElement, parameters);
-          result[i] = new CandidateInfo(resolveResult, substitutor);
+          PsiSubstitutor substitutor = resolveResult.getSubstitutor();
+          result[i] = new CandidateInfo(resolveResult, substitutor) {
+            @NotNull
+            @Override
+            public PsiSubstitutor getSubstitutor() {
+              final PsiType[] parameters = ref.getTypeParameters();
+              return super.getSubstitutor().putAll((PsiClass)resultElement, parameters);
+            }
+          };
         }
       }
     }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
index a52ea73..b4b188c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
@@ -18,7 +18,6 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeEqualityConstraint;
-import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.Nullable;
@@ -102,7 +101,7 @@
         return null;
       }
 
-      final PsiSubstitutor substitutor = session.resolveDependencies(session.getInferenceVariables());
+      final PsiSubstitutor substitutor = session.retrieveNonPrimitiveEqualsBounds(session.getInferenceVariables());
       final PsiType[] newTypeParameters = new PsiType[parameters.length];
       for (int i = 0; i < typeParameters.length; i++) {
         PsiTypeParameter typeParameter = typeParameters[i];
@@ -119,14 +118,10 @@
         return null;
       }
 
-      if (!TypeConversionUtil.containsWildcards(parameterization)) {
+      if (!TypeConversionUtil.containsWildcards(parameterization) && psiClassType.isAssignableFrom(parameterization)) {
         return parameterization;
       }
 
-      if (!psiClassType.isAssignableFrom(parameterization)) {
-        return null;
-      }
-
       return getNonWildcardParameterization((PsiClassType)psiClassType);
     }
     return null;
@@ -169,27 +164,32 @@
       for (int i = 0; i < parameters.length; i++) {
         PsiType paramType = parameters[i];
         if (paramType instanceof PsiWildcardType) {
-          final PsiClassType[] extendsListTypes = typeParameters[i].getExtendsListTypes();
-          final PsiClassType Bi = extendsListTypes.length > 0 ? extendsListTypes[0]
-                                                              : PsiType.getJavaLangObject(psiClass.getManager(),
-                                                                                          GlobalSearchScope.allScope(psiClass.getProject()));
-          if (PsiPolyExpressionUtil.mentionsTypeParameters(Bi, typeParametersSet)) {
-            return null;
+          final PsiType bound = GenericsUtil.eliminateWildcards(((PsiWildcardType)paramType).getBound(), false);
+          if (((PsiWildcardType)paramType).isSuper()) {
+            newParameters[i] = bound;
           }
-
-          final PsiType bound = ((PsiWildcardType)paramType).getBound();
-          if (bound == null) {
-            newParameters[i] = Bi;
-          } else if (((PsiWildcardType)paramType).isExtends()){
-            newParameters[i] = GenericsUtil.getGreatestLowerBound(Bi, GenericsUtil.eliminateWildcards(bound, false));
-          } else {
-            newParameters[i] = GenericsUtil.eliminateWildcards(bound, false);
+          else {
+            newParameters[i] = bound != null ? bound : PsiType.getJavaLangObject(psiClass.getManager(), psiClassType.getResolveScope());
+            for (PsiClassType paramBound : typeParameters[i].getExtendsListTypes()) {
+              if (!PsiPolyExpressionUtil.mentionsTypeParameters(paramBound, typeParametersSet)) {
+                newParameters[i] = GenericsUtil.getGreatestLowerBound(paramBound, newParameters[i]);
+              }
+            }
           }
         } else {
           newParameters[i] = paramType;
         }
       }
-      return JavaPsiFacade.getElementFactory(psiClass.getProject()).createType(psiClass, newParameters);
+
+      if (!isWellFormed(psiClass, typeParameters, newParameters)) {
+        return null;
+      }
+
+      final PsiClassType parameterization = JavaPsiFacade.getElementFactory(psiClass.getProject()).createType(psiClass, newParameters);
+      if (!psiClassType.isAssignableFrom(parameterization)) {
+        return null;
+      }
+      return parameterization;
     }
     return null;
   }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
index cc66681..f30c7ae 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
@@ -110,18 +110,6 @@
           }
         }
       }
-
-      //todo no such a rule in spec?!
-      for (PsiType lowerBound : lowerBounds) {
-        if (mySession.isProperType(lowerBound)) {
-          final PsiSubstitutor substitutor = PsiSubstitutor.EMPTY.put(inferenceVariable.getParameter(), lowerBound);
-          for (PsiType upperBound : upperBounds) {
-            if (!mySession.isProperType(upperBound)) {
-              addConstraint(new StrictSubtypingConstraint(substitutor.substitute(upperBound), lowerBound));
-            }
-          }
-        }
-      }
     }
 
     for (Pair<PsiTypeParameter[], PsiClassType> capture : myCaptures) {
@@ -389,21 +377,4 @@
       }
     }
   }
-
-  public PsiSubstitutor checkIncorporated(PsiSubstitutor substitutor, Collection<InferenceVariable> variables) {
-    for (InferenceVariable variable : variables) { //todo equals bounds?
-      for (PsiType lowerBound : variable.getBounds(InferenceBound.LOWER)) {
-        lowerBound = substitutor.substitute(lowerBound);
-        if (mySession.isProperType(lowerBound)) {
-          for (PsiType upperBound : variable.getBounds(InferenceBound.UPPER)) {
-            upperBound = substitutor.substitute(upperBound);
-            if (mySession.isProperType(upperBound) && !TypeConversionUtil.isAssignable(upperBound, lowerBound)) {
-              return null;
-            }
-          }
-        }
-      }
-    }
-    return substitutor;
-  }
 }
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
index abde461..5391101 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
@@ -20,15 +20,8 @@
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.Pair;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.PsiImplUtil;
 import com.intellij.psi.impl.source.resolve.graphInference.constraints.*;
 import com.intellij.psi.infos.MethodCandidateInfo;
-import com.intellij.psi.scope.MethodProcessorSetupFailedException;
-import com.intellij.psi.scope.PsiConflictResolver;
-import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
-import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
-import com.intellij.psi.scope.processor.MethodResolverProcessor;
-import com.intellij.psi.scope.util.PsiScopesUtil;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiTypesUtil;
@@ -174,7 +167,8 @@
     return true;
   }
 
-  private static PsiType getParameterType(PsiParameter[] parameters, PsiExpression[] args, int i, PsiSubstitutor substitutor) {
+  private static PsiType getParameterType(PsiParameter[] parameters, PsiExpression[] args, int i, @Nullable PsiSubstitutor substitutor) {
+    if (substitutor == null) return null;
     PsiType parameterType = substitutor.substitute(parameters[i < parameters.length ? i : parameters.length - 1].getType());
     if (parameterType instanceof PsiEllipsisType) {
       final PsiExpression arg = args[i];
@@ -213,7 +207,7 @@
                                     PsiMethod parentMethod) {
     if (!repeatInferencePhases(true)) {
       //inferred result would be checked as candidate won't be applicable
-      return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor, false);
+      return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor);
     }
 
     if (parentMethod != null) {
@@ -299,17 +293,17 @@
         }
       }
     } else {
-      return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor, false);
+      return resolveSubset(myInferenceVariables.values(), mySiteSubstitutor);
     }
 
     return prepareSubstitution();
   }
 
-  public PsiSubstitutor resolveDependencies(Collection<InferenceVariable> variables) {
+  public PsiSubstitutor retrieveNonPrimitiveEqualsBounds(Collection<InferenceVariable> variables) {
     PsiSubstitutor substitutor = mySiteSubstitutor;
     for (InferenceVariable variable : variables) {
       final PsiType equalsBound = getEqualsBound(variable, substitutor);
-      if (equalsBound != PsiType.NULL) {
+      if (!(equalsBound instanceof PsiPrimitiveType)) {
         substitutor = substitutor.put(variable.getParameter(), equalsBound);
       }
     }
@@ -340,9 +334,13 @@
     return false;
   }
 
-  public void initBounds(PsiTypeParameter... typeParameters) {
+  public boolean initBounds(PsiTypeParameter... typeParameters) {
+    boolean sameMethodCall = false;
     for (PsiTypeParameter parameter : typeParameters) {
-      if (myInferenceVariables.containsKey(parameter)) continue;
+      if (myInferenceVariables.containsKey(parameter)) {
+        sameMethodCall = true;
+        continue;
+      }
       InferenceVariable variable = new InferenceVariable(parameter);
       boolean added = false;
       final PsiClassType[] extendsListTypes = parameter.getExtendsListTypes();
@@ -359,29 +357,19 @@
       }
       myInferenceVariables.put(parameter, variable);
     }
-  }
-  
-  public void addCapturedVariable(PsiTypeParameter param) {
-    initBounds(param);
+    return sameMethodCall;
   }
 
   private void initReturnTypeConstraint(PsiMethod method, final PsiCallExpression context) {
-    if (PsiPolyExpressionUtil.isMethodCallPolyExpression(context, method) || 
-        context instanceof PsiNewExpression && PsiDiamondType.ourDiamondGuard.currentStack().contains(context)) {
+    if (PsiPolyExpressionUtil.isMethodCallPolyExpression(context, method)) {
       PsiType returnType = method.getReturnType();
       if (!PsiType.VOID.equals(returnType) && returnType != null) {
-        returnType = PsiImplUtil.normalizeWildcardTypeByPosition(returnType, context);
         PsiType targetType = PsiTypesUtil.getExpectedTypeByParent(context);
         if (targetType == null) {
-          targetType = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(context, false, new Computable<PsiType>() {
-            @Override
-            public PsiType compute() {
-              return getTargetType(context);
-            }
-          });
+          targetType = getTargetType(context);
         }
         if (targetType != null) {
-          registerConstraints(returnType, targetType);
+          registerConstraints(PsiUtil.isRawSubstitutor(method, mySiteSubstitutor) ? returnType : mySiteSubstitutor.substitute(returnType), targetType);
         }
       }
     }
@@ -397,7 +385,7 @@
   public void registerConstraints(PsiType returnType, PsiType targetType) {
     final InferenceVariable inferenceVariable = shouldResolveAndInstantiate(returnType, targetType);
     if (inferenceVariable != null) {
-      final PsiSubstitutor substitutor = resolveSubset(Collections.singletonList(inferenceVariable), mySiteSubstitutor, true);
+      final PsiSubstitutor substitutor = resolveSubset(Collections.singletonList(inferenceVariable), mySiteSubstitutor);
       myConstraints.add(new TypeCompatibilityConstraint(targetType, PsiUtil.captureToplevelWildcards(substitutor.substitute(inferenceVariable.getParameter()), myContext)));
     } 
     else {
@@ -412,7 +400,7 @@
           PsiTypeParameter[] copy = new PsiTypeParameter[typeParameters.length];
           for (int i = 0; i < typeParameters.length; i++) {
             PsiTypeParameter typeParameter = typeParameters[i];
-            copy[i] = elementFactory.createTypeParameterFromText(typeParameter.getName(), null);
+            copy[i] = elementFactory.createTypeParameterFromText("rCopy" + typeParameter.getName(), null);
             initBounds(copy[i]);
             subst = subst.put(typeParameter, elementFactory.createType(copy[i]));
           }
@@ -495,7 +483,7 @@
     return false;
   }
   
-  private PsiType getTargetType(final PsiExpression context) {
+  private static PsiType getTargetType(final PsiExpression context) {
     final PsiElement parent = PsiUtil.skipParenthesizedExprUp(context.getParent());
     if (parent instanceof PsiExpressionList) {
       PsiElement gParent = parent.getParent();
@@ -505,28 +493,8 @@
       if (gParent instanceof PsiCallExpression) {
         final PsiExpressionList argumentList = ((PsiCallExpression)gParent).getArgumentList();
         if (argumentList != null) {
-          final Pair<PsiMethod, PsiSubstitutor> pair = MethodCandidateInfo.getCurrentMethod(argumentList);
-          final PsiFile placeFile = context.getContainingFile();
-          final JavaMethodsConflictResolver conflictResolver = new JavaMethodsConflictResolver(argumentList, PsiUtil.getLanguageLevel(placeFile)){
-            @Override
-            protected PsiType[] getArgumentTypes() {
-              return InferenceSession.getArgumentTypes(argumentList, context);
-            }
-          };
-          final MethodCandidatesProcessor processor = new MethodResolverProcessor((PsiCallExpression)gParent, placeFile, new PsiConflictResolver[]{conflictResolver}) {
-            @Override
-            protected PsiType[] getExpressionTypes(PsiExpressionList argumentList) {
-              return getArgumentTypes(argumentList, context);
-            }
-          };
-          try {
-            PsiScopesUtil.setupAndRunProcessor(processor, (PsiCallExpression)gParent, false);
-          }
-          catch (MethodProcessorSetupFailedException e) {
-            return null;
-          }
-          final JavaResolveResult[] results = processor.getResult();
-          return results.length == 1 ? getTypeByMethod(context, argumentList, pair, results[0], results[0].getElement()) : null;
+          final JavaResolveResult result = ((PsiCallExpression)gParent).resolveMethodGenerics();
+          return getTypeByMethod(context, argumentList, result, result.getElement());
         }
       }
     } else if (parent instanceof PsiConditionalExpression) {
@@ -546,30 +514,9 @@
     return null;
   }
 
-  private static PsiType[] getArgumentTypes(PsiExpressionList argumentList, PsiExpression context) {
-    if (argumentList != null) {
-      final PsiExpression[] expressions = argumentList.getExpressions();
-      final int idx = LambdaUtil.getLambdaIdx(argumentList, context);
-      final PsiType[] types = PsiType.createArray(expressions.length);
-      for (int i = 0; i < expressions.length; i++) {
-        if (i != idx) {
-          types[i] = expressions[i].getType();
-        }
-        else {
-          types[i] = PsiType.NULL;
-        }
-      }
-      return types;
-    }
-    else {
-      return null;
-    }
-  }
-
-  private PsiType getTypeByMethod(PsiExpression context,
-                                  PsiExpressionList argumentList,
-                                  Pair<PsiMethod, PsiSubstitutor> pair,
-                                  JavaResolveResult result, PsiElement parentMethod) {
+  private static PsiType getTypeByMethod(PsiExpression context,
+                                         PsiExpressionList argumentList,
+                                         final JavaResolveResult result, PsiElement parentMethod) {
     if (parentMethod instanceof PsiMethod) {
       final PsiParameter[] parameters = ((PsiMethod)parentMethod).getParameterList().getParameters();
       if (parameters.length == 0) return null;
@@ -581,23 +528,13 @@
       }
       final int i = ArrayUtilRt.find(args, arg);
       if (i < 0) return null;
-      final PsiCallExpression callExpression = PsiTreeUtil.getParentOfType(argumentList, PsiCallExpression.class);
-      if (callExpression != null && callExpression.getTypeArguments().length > 0) {
-        return getParameterType(parameters, args, i, ((MethodCandidateInfo)result).typeArgumentsSubstitutor());
-      }
-      final PsiType parameterType = getParameterType(parameters, args, i, pair != null ? pair.second : PsiSubstitutor.EMPTY);
-      args[i] = null;
-      final PsiTypeParameter[] typeParameters = ((PsiMethod)parentMethod).getTypeParameters();
-      final InferenceSession session = new InferenceSession(typeParameters, ((MethodCandidateInfo)result).getSiteSubstitutor(), myManager, argumentList);
-      session.initExpressionConstraints(parameters, args, argumentList, (PsiMethod)parentMethod);
-      if (session.tryToInfer(parameters, args, callExpression, (PsiMethod)parentMethod) != null) {
-        return null;
-      }
-      final Collection<PsiTypeParameter> params = session.getTypeParams();
-      initBounds(params.toArray(new PsiTypeParameter[params.size()]));
-      liftBounds(session.getInferenceVariables());
-      final PsiSubstitutor substitutor = ((MethodCandidateInfo)result).getSiteSubstitutor();
-      return substitutor.substitute(parameterType);
+      return getParameterType(parameters, args, i, PsiResolveHelper.ourGraphGuard.doPreventingRecursion(argumentList.getParent(), false,
+                                                                                                        new Computable<PsiSubstitutor>() {
+                                                                                                          @Override
+                                                                                                          public PsiSubstitutor compute() {
+                                                                                                            return result.getSubstitutor();
+                                                                                                          }
+                                                                                                        }));
     }
     return null;
   }
@@ -720,7 +657,7 @@
     while (!allVars.isEmpty()) {
       final List<InferenceVariable> vars = InferenceVariablesOrder.resolveOrder(allVars, this);
       if (!myIncorporationPhase.hasCaptureConstraints(vars)) {
-        final PsiSubstitutor firstSubstitutor = resolveSubset(vars, substitutor, true);
+        final PsiSubstitutor firstSubstitutor = resolveSubset(vars, substitutor);
         if (firstSubstitutor != null) {
           substitutor = firstSubstitutor;
           allVars.removeAll(vars);
@@ -731,7 +668,7 @@
       final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(getManager().getProject());
       for (InferenceVariable var : vars) {
         final PsiTypeParameter parameter = var.getParameter();
-        final PsiTypeParameter copy = elementFactory.createTypeParameterFromText(parameter.getName(), null);
+        final PsiTypeParameter copy = elementFactory.createTypeParameterFromText("z" + parameter.getName(), null);
         final PsiType lub = getLowerBound(var, substitutor);
         final PsiType glb = getUpperBound(var, substitutor);
         final InferenceVariable zVariable = new InferenceVariable(copy);
@@ -744,6 +681,8 @@
           zVariable.addBound(lub, InferenceBound.LOWER);
         }
         myInferenceVariables.put(copy, zVariable);
+        allVars.add(zVariable);
+        var.addBound(elementFactory.createType(copy), InferenceBound.EQ);
       }
       myIncorporationPhase.forgetCaptures(vars);
       if (!myIncorporationPhase.incorporate()) {
@@ -762,7 +701,7 @@
     }, substitutor);
   }
 
-  private PsiSubstitutor resolveSubset(Collection<InferenceVariable> vars, PsiSubstitutor substitutor, boolean checkResult) {
+  private PsiSubstitutor resolveSubset(Collection<InferenceVariable> vars, PsiSubstitutor substitutor) {
     for (InferenceVariable var : vars) {
       LOG.assertTrue(var.getInstantiation() == PsiType.NULL);
       final PsiTypeParameter typeParameter = var.getParameter();
@@ -781,7 +720,7 @@
       }
     }
 
-    return checkResult ? myIncorporationPhase.checkIncorporated(substitutor, vars) : substitutor;
+    return substitutor;
   }
 
   private PsiType getUpperBound(InferenceVariable var, PsiSubstitutor substitutor) {
@@ -872,7 +811,7 @@
       }
 
       //resolve input variables
-      PsiSubstitutor substitutor = resolveSubset(varsToResolve, mySiteSubstitutor, true);
+      PsiSubstitutor substitutor = resolveSubset(varsToResolve, mySiteSubstitutor);
 
       if (substitutor == null) {
         return false;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java
index a67b64e..a629175 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java
@@ -48,17 +48,6 @@
     if (!PsiPolyExpressionUtil.isPolyExpression(myExpression)) {
       return true;
     }
-    if (myExpression instanceof PsiCallExpression) {
-      final PsiExpressionList argumentList = ((PsiCallExpression)myExpression).getArgumentList();
-      if (argumentList != null) {
-        for (PsiExpression expression : argumentList.getExpressions()) {
-          if (PsiPolyExpressionUtil.isPolyExpression(expression)) {
-            //todo additional constraints [JDK-8033488]
-          }
-        }
-      }
-      return true;
-    }
     if (myExpression instanceof PsiParenthesizedExpression) {
       constraints.add(new CheckedExceptionCompatibilityConstraint(((PsiParenthesizedExpression)myExpression).getExpression(), myT));
       return true;
@@ -122,7 +111,7 @@
         final PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
         final PsiMethod method;
         if (((PsiMethodReferenceExpression)myExpression).isExact()) {
-          final PsiElement resolve = ((PsiMethodReferenceExpression)myExpression).resolve();
+          final PsiElement resolve = ((PsiMethodReferenceExpression)myExpression).getPotentiallyApplicableMember();
           if (resolve instanceof PsiMethod) {
             method = (PsiMethod)resolve;
           } else {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
index 30628e3..ebcbda6 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
@@ -21,10 +21,13 @@
 import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
 import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
 import com.intellij.psi.infos.MethodCandidateInfo;
+import com.intellij.psi.util.PsiUtil;
 import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.util.containers.HashSet;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -99,22 +102,51 @@
 
         if (typeParams != null) {
 
-          for (PsiTypeParameter typeParam : typeParams) {
-            session.addCapturedVariable(typeParam);
-          }
+          final HashSet<PsiTypeParameter> oldBounds = new HashSet<PsiTypeParameter>(session.getTypeParams());
+          final boolean sameMethodCall = session.initBounds(typeParams);
           PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
+          final HashSet<InferenceVariable> variables = new HashSet<InferenceVariable>();
+          session.collectDependencies(returnType, variables);
+          final PsiTypeParameter[] params = new PsiTypeParameter[typeParams.length];
+          for (int i = 0; i < typeParams.length; i++) {
+            if (variables.contains(session.getInferenceVariable(typeParams[i]))) {
+              params[i] = JavaPsiFacade.getElementFactory(myExpression.getProject()).createTypeParameterFromText("copyOf" + myExpression.hashCode() + typeParams[i].getName(), null);
+              substitutor = substitutor.put(typeParams[i], JavaPsiFacade.getElementFactory(myExpression.getProject()).createType(params[i]));
+            }
+            else {
+              params[i] = typeParams[i];
+            }
+          }
+          final PsiSubstitutor siteSubstitutor = resolveResult instanceof MethodCandidateInfo && method != null && !method.isConstructor() 
+                                                 ? ((MethodCandidateInfo)resolveResult).getSiteSubstitutor() : PsiSubstitutor.EMPTY;
+          for (PsiTypeParameter typeParameter : siteSubstitutor.getSubstitutionMap().keySet()) {
+            substitutor = substitutor.put(typeParameter, substitutor.substitute(siteSubstitutor.substitute(typeParameter)));
+          }
+
+          final Collection<PsiTypeParameter> params1 = session.getTypeParams();
+          final InferenceSession callSession = new InferenceSession(params1.toArray(new PsiTypeParameter[params1.size()]), substitutor, myExpression.getManager(), myExpression);
+          callSession.initBounds(params);
           if (method != null) {
-            //typeParams are already included
-            final Collection<PsiTypeParameter> params = session.getTypeParams();
-            InferenceSession callSession = new InferenceSession(params.toArray(new PsiTypeParameter[params.size()]), resolveResult instanceof MethodCandidateInfo ? ((MethodCandidateInfo)resolveResult).getSiteSubstitutor() 
-                                                                                                                                                                  : PsiSubstitutor.EMPTY, myExpression.getManager(), myExpression);
             final PsiExpression[] args = argumentList.getExpressions();
             final PsiParameter[] parameters = method.getParameterList().getParameters();
             callSession.initExpressionConstraints(parameters, args, myExpression, method);
-            callSession.registerConstraints(returnType, myT);
-            if (callSession.repeatInferencePhases(true)) {
-              session.liftBounds(callSession.getInferenceVariables());
+          }
+          final boolean accepted = callSession.repeatInferencePhases(true);
+          if (!accepted) {
+            //todo return false;
+          }
+          callSession.registerConstraints(method != null && !PsiUtil.isRawSubstitutor(method, siteSubstitutor) ? siteSubstitutor.substitute(returnType) : returnType, substitutor.substitute(returnType));
+          if (callSession.repeatInferencePhases(true)) {
+            final Collection<InferenceVariable> inferenceVariables = callSession.getInferenceVariables();
+            if (sameMethodCall) {
+              for (Iterator<InferenceVariable> iterator = inferenceVariables.iterator(); iterator.hasNext(); ) {
+                InferenceVariable variable = iterator.next();
+                if (oldBounds.contains(variable.getParameter())) {
+                  iterator.remove();
+                }
+              }
             }
+            session.liftBounds(inferenceVariables);
           }
           final PsiType capturedReturnType = myExpression instanceof PsiMethodCallExpression
                                              ? PsiMethodCallExpressionImpl.captureReturnType((PsiMethodCallExpression)myExpression, method, returnType, substitutor)
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java
index 7e2443a..cbb1db8 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeEqualityConstraint.java
@@ -109,6 +109,11 @@
       return true;
     }
 
+    if (myT instanceof PsiCapturedWildcardType && myS instanceof PsiCapturedWildcardType) {
+      return new TypeEqualityConstraint(((PsiCapturedWildcardType)myT).getWildcard(), 
+                                        ((PsiCapturedWildcardType)myS).getWildcard()).reduce(session, constraints);
+    }
+
     return false;
   }
 
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java
index 58c2970..18ff2d1 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java
@@ -25,7 +25,6 @@
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.CharTable;
 import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.SmartList;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -55,18 +54,19 @@
     return type;
   }
 
+  // collects annotations bound to C-style arrays
   private static List<PsiAnnotation[]> collectAnnotations(PsiElement anchor, PsiAnnotation stopAt) {
-    List<PsiAnnotation[]> annotations = new SmartList<PsiAnnotation[]>();
+    List<PsiAnnotation[]> annotations = ContainerUtil.newSmartList();
 
     List<PsiAnnotation> current = null;
-    boolean stop = false;
+    boolean found = (stopAt == null), stop = false;
     for (PsiElement child = anchor.getNextSibling(); child != null; child = child.getNextSibling()) {
       if (child instanceof PsiComment || child instanceof PsiWhiteSpace) continue;
 
       if (child instanceof PsiAnnotation) {
-        if (current == null) current = new SmartList<PsiAnnotation>();
+        if (current == null) current = ContainerUtil.newSmartList();
         current.add((PsiAnnotation)child);
-        if (child == stopAt) stop = true;
+        if (child == stopAt) found = stop = true;
         continue;
       }
 
@@ -80,8 +80,8 @@
       }
     }
 
-    // stop == true means annotation is misplaced
-    return stop ? null : annotations;
+    // annotation is misplaced (either located before the anchor or has no following brackets)
+    return !found || stop ? null : annotations;
   }
 
   public static void normalizeBrackets(@NotNull PsiVariable variable) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java
index f6ba9fd..918d7fe 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaTreeGenerator.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.
@@ -131,7 +131,7 @@
         type = PsiType.getJavaLangObject(manager, GlobalSearchScope.projectScope(manager.getProject()));
       }
 
-      String text = type.getPresentableText();
+      String text = type.getCanonicalText(true);
       PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(original.getProject()).getParserFacade();
       PsiTypeElement element = parserFacade.createTypeElementFromText(text, original);
 
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java
index cf40d04..1d8693e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -38,7 +38,8 @@
 
   @Override
   public void replaceChildInternal(@NotNull ASTNode child, @NotNull TreeElement newElement) {
-    if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) {
+    if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType()) &&
+        ElementType.EXPRESSION_BIT_SET.contains(newElement.getElementType())) {
       boolean needParenth = ReplaceExpressionUtil.isNeedParenthesis(child, newElement);
       if (needParenth) {
         newElement = SourceUtil.addParenthToReplacedChild(JavaElementType.PARENTH_EXPRESSION, newElement, getManager());
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java
index fdd02e8..084be88 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java
@@ -499,6 +499,7 @@
                         final PsiClass pClass = pResult.getElement();
                         final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil.getClassSubstitutor(containingClass, pClass, pResult.getSubstitutor()) : null;
                         if (receiverSubstitutor != null) {
+                          if (!method.hasTypeParameters() && signature.getParameterTypes().length == 1) return receiverSubstitutor;
                           psiSubstitutor = receiverSubstitutor;
                         }
                       }
@@ -638,20 +639,26 @@
           }
         }
 
+        if (myQualifierResolveResult.isReferenceTypeQualified() && getReferenceNameElement() instanceof PsiIdentifier) {
+          //If the first search produces a static method, and no non-static method is applicable for the second search, then the result of the first search is the compile-time declaration.
+          CandidateInfo candidateInfo = filterStaticCorrectCandidates(firstCandidates, secondCandidates, true);
+          if (candidateInfo != null) {
+            return candidateInfo;
+          }
+
+          //If the second search produces a non-static method, and no static method is applicable for the first search, then the result of the second search is the compile-time declaration.
+          candidateInfo = filterStaticCorrectCandidates(secondCandidates, firstCandidates, false);
+          if (candidateInfo != null) {
+            return candidateInfo;
+          }
+        }
+
         checkSpecifics(firstCandidates,
                        varargs ? MethodCandidateInfo.ApplicabilityLevel.VARARGS : MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY, myLanguageLevel);
 
         checkSpecifics(secondCandidates, 
                        varargs ? MethodCandidateInfo.ApplicabilityLevel.VARARGS : MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY, myLanguageLevel);
 
-        if (myQualifierResolveResult.isReferenceTypeQualified() && getReferenceNameElement() instanceof PsiIdentifier) {
-          //If the first search produces a static method, and no non-static method is applicable for the second search, then the result of the first search is the compile-time declaration.
-          filterStaticCorrectCandidates(firstCandidates, true);
-
-          //If the second search produces a non-static method, and no static method is applicable for the first search, then the result of the second search is the compile-time declaration.
-          filterStaticCorrectCandidates(secondCandidates, false);
-        }
-
         final int acceptedCount = firstCandidates.size() + secondCandidates.size();
         if (acceptedCount == 1) {
           return !firstCandidates.isEmpty() ? firstCandidates.get(0) : secondCandidates.get(0);
@@ -684,17 +691,29 @@
       /**
        * 15.13.1
        */
-      private void filterStaticCorrectCandidates(List<CandidateInfo> firstCandidates,
+      private CandidateInfo filterStaticCorrectCandidates(List<CandidateInfo> firstCandidates,
+                                                 List<CandidateInfo> secondCandidates, 
                                                  boolean shouldBeStatic) {
-        for (Iterator<CandidateInfo> iterator = firstCandidates.iterator(); iterator.hasNext(); ) {
-          final PsiElement element = iterator.next().getElement();
+        if (firstCandidates.size() == 1) {
+          final CandidateInfo candidateInfo = firstCandidates.get(0);
+          final PsiElement element = candidateInfo.getElement();
           if (element instanceof PsiMethod) {
             final boolean isStatic = ((PsiMethod)element).hasModifierProperty(PsiModifier.STATIC);
-            if (shouldBeStatic && !isStatic || !shouldBeStatic && isStatic) {
-              iterator.remove();
+            if (shouldBeStatic && isStatic || !shouldBeStatic && !isStatic) {
+              for (CandidateInfo secondCandidate : secondCandidates) {
+                final PsiElement psiElement = secondCandidate.getElement();
+                if (psiElement instanceof PsiMethod) {
+                  final boolean oppositeStatic = ((PsiMethod)psiElement).hasModifierProperty(PsiModifier.STATIC);
+                  if (shouldBeStatic && !oppositeStatic || !shouldBeStatic && oppositeStatic) {
+                    return null;
+                  }
+                }
+              }
+              return candidateInfo;
             }
           }
         }
+        return null;
       }
 
       private boolean isCorrectAssignment(PsiType[] signatureParameterTypes2,
diff --git a/java/java-tests/testData/codeInsight/completion/normal/MulticaretTyping.java b/java/java-tests/testData/codeInsight/completion/normal/MulticaretTyping.java
new file mode 100644
index 0000000..00d3186
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/MulticaretTyping.java
@@ -0,0 +1,4 @@
+class Foo {{
+  System.out.p<caret>
+  System.out.p<caret>
+}}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/MulticaretTyping_after.java b/java/java-tests/testData/codeInsight/completion/normal/MulticaretTyping_after.java
new file mode 100644
index 0000000..87debd8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/MulticaretTyping_after.java
@@ -0,0 +1,4 @@
+class Foo {{
+  System.out.append(<caret>)
+  System.out.append(<caret>)
+}}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java
index 506accd..d0d4dbc 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java
@@ -27,7 +27,7 @@
     for (String s : args) { System.out.println(s); }
 
     List<String> list =
-      new ArrayList<>();
+      new ArrayList<error descr="Diamond types are not supported at this language level"><></error>();
 
     for (String s : list) {}
     Arrays.asList("");
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java
index f51647a..fbbe916 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/DiamondMisc.java
@@ -97,14 +97,14 @@
 class FI1 {
   I<? extends String> i1 = new I<<error descr="Cannot use ''<>'' with anonymous inner classes"></error>>() {
     @Override
-    public <error descr="'m()' in 'Anonymous class derived from I' clashes with 'm()' in 'I'; attempting to use incompatible return type">String</error> m() {
+    public String m() {
       return null;
     }
   };
 
   I<?> i2 = new I<<error descr="Cannot use ''<>'' with anonymous inner classes"></error>>() {
     @Override
-    public <error descr="'m()' in 'Anonymous class derived from I' clashes with 'm()' in 'I'; attempting to use incompatible return type">Object</error> m() {
+    public Object m() {
       return null;
     }
   };
@@ -157,14 +157,14 @@
 class TestWildcardInference {
   interface A<T> {
   }
-  
+
   class B<V> implements A<V> {
     B(C<V> v) {
     }
   }
-  
+
   class C<E> {}
-  
+
   class U {
     void foo() {
       C<? extends Number> x = null;
@@ -202,13 +202,13 @@
 
         System.out.println(i);
 
-        <error descr="Incompatible types. Found: 'Outer2.Inner2<java.lang.String>', required: 'Outer2.Inner2<java.lang.String>'">Outer2<Integer>.Inner2<String> i5 = new Outer2<>().new Inner2<>();</error>
+        <error descr="Incompatible types. Found: 'Outer2.Inner2<java.lang.String>', required: 'Outer2<java.lang.Integer>.Inner2<java.lang.String>'">Outer2<Integer>.Inner2<String> i5 = new Outer2<>().new Inner2<>();</error>
     }
 
   static Outer m() {return null;}
   static <T extends Outer> T m1() {return null;}
   static <T> T m2() {return null;}
-  
+
 }
 
 class TypeParamsExtendsList {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/typeAnnotations.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/typeAnnotations.java
index 400a678..28035c8 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/typeAnnotations.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/typeAnnotations.java
@@ -111,6 +111,7 @@
     int @TA [] a @TA [] <error descr="Annotations are not allowed here">@TA</error> = (p != null ? p : mixedArrays);
     return a;
   }
+  void <error descr="Annotations are not allowed here">@TA</error> misplaced() { }
 
   @TA Outer() { }
 
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57413.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57413.java
index 7236a9b..de27a24 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57413.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57413.java
@@ -2,6 +2,6 @@
     <T extends A<T>> void foo(T x){}
 
     void bar(A<?> x){
-        <error descr="Inferred type 'A<capture<?>>' for type parameter 'T' is not within its bound; should extend 'A<A<capture<?>>>'">foo(x)</error>;
+        <error descr="Inferred type 'capture<?>' for type parameter 'T' is not within its bound; should extend 'A<capture<? extends A<capture<?>>>>'">foo(x)</error>;
     }
 }
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java
index 7556292..298a33d 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java
@@ -142,7 +142,7 @@
     }
 
     void bar(List<? extends S1> k) {
-        f<error descr="'f(java.util.List<capture<? extends S1>>, capture<? extends S1>)' in 'S1' cannot be applied to '(java.util.List<capture<? extends S1>>, S1)'">(k,  k.get(0))</error>;
+        f<error descr="'f(java.util.List<capture<? extends S1>>, capture<? extends S1>)' in 'S1' cannot be applied to '(java.util.List<capture<? extends S1>>, capture<? extends S1>)'">(k,  k.get(0))</error>;
     }
 }
 
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/LiftedCaptureToOuterCall.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/LiftedCaptureToOuterCall.java
new file mode 100644
index 0000000..75d3b8a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/LiftedCaptureToOuterCall.java
@@ -0,0 +1,16 @@
+class Test {
+
+  class Foo<K> {}
+
+  void test(Foo<? extends String> p) {
+    foo(bar(p)) ;
+  }
+
+  <T> T bar(Foo<T> p) {
+    return null;
+  }
+
+  <K> K foo(K p) {
+    return null;
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/NestedCallsSameMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/NestedCallsSameMethod.java
index eaafb1b..458171f 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/NestedCallsSameMethod.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/NestedCallsSameMethod.java
@@ -1,3 +1,41 @@
+import java.util.List;
+
+import java.util.function.Function;
+
+abstract class Main2 {
+  void address(Foo sa) {
+    String ds = foobar(foobar(sa, Foo::getBar), Bar ::getName);
+    Function<Foo, Bar> f = null;
+    String ds1 = foobar(foobar(sa, f), null);
+  }
+
+  abstract <T, V> V foobar(T t, Function<T, V> mapper);
+
+  class Foo {
+    Bar getBar() {
+      return new Bar();
+    }
+  }
+
+  class Bar {
+    String getName(){
+      return null;
+    }
+  }
+}
+
+
+class Main0 {
+  <T> List<T> foo(T t){
+    return null;
+  }
+
+  {
+    foo(foo(""));
+  }
+}
+
+
 class Main {
     static <T> T foo(T t) { return null; }
 
@@ -14,6 +52,6 @@
   static <B> B bar(B t) { return null;}
 
   static {
-    long l = foo(bar(1));
+    //long l = foo(bar(1));
   }
 }
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/SiteSubstitutionForReturnConstraint.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/SiteSubstitutionForReturnConstraint.java
new file mode 100644
index 0000000..ca5ad38
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/SiteSubstitutionForReturnConstraint.java
@@ -0,0 +1,21 @@
+import java.util.function.Function;
+import java.util.stream.Collector;
+
+class Collectors {
+
+  public static <A,R,RR> void collectingAndThen(Function<R, RR> finisher, Function<A, R> finisher1) {
+    Function<A, RR> f = finisher1.andThen(finisher);
+  }
+
+}
+
+
+class Collectors1 {
+  public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Function<R, RR> finisher, Function<A, R> function) {
+    return factory(function.andThen(finisher));
+  }
+
+  static <Ts, As, Rs> Collector<Ts, As, Rs> factory(Function<As, Rs> f) {
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeAmbiguity.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeAmbiguity.java
index 8ee9852..70a6e70 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeAmbiguity.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeAmbiguity.java
@@ -40,6 +40,6 @@
   }
 
   public static void main(Promise<String> helloWorld) {
-    helloWorld.then<error descr="Ambiguous method call: both 'Promise.then(Function<? super String,Promise<Integer>>)' and 'Promise.then(AsyncFunction<? super String,Promise<Integer>>)' match">(AAmbiguous::calculateLength)</error>;
+    helloWorld.then<error descr="Ambiguous method call: both 'Promise.then(Function<? super String, Promise<Integer>>)' and 'Promise.then(AsyncFunction<? super String, Promise<Integer>>)' match">(AAmbiguous::calculateLength)</error>;
   }
 }
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility1.java
index 84e9296..d62afb3 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility1.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility1.java
@@ -21,9 +21,9 @@
     }
 
     void foo(Foo<String> as, final Foo<Character> ac) {
-        boolean b1 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character,Boolean>)' and 'Foo.forAll(II<Character,String>)' match">(c -> false)</error>);
-        String s1 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character,Boolean>)' and 'Foo.forAll(II<Character,String>)' match">(c -> "")</error>);
-        boolean b2 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character,Boolean>)' and 'Foo.forAll(II<Character,String>)' match">(c -> "")</error>);
+        boolean b1 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character, Boolean>)' and 'Foo.forAll(II<Character, String>)' match">(c -> false)</error>);
+        String s1 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character, Boolean>)' and 'Foo.forAll(II<Character, String>)' match">(c -> "")</error>);
+        boolean b2 = as.forAll(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character, Boolean>)' and 'Foo.forAll(II<Character, String>)' match">(c -> "")</error>);
         String s2 = as.forAll2(s -> ac.forAll2(<error descr="Incompatible return type boolean in lambda expression">c -> false</error>));
         boolean b3 = as.forAll((I<String, Boolean>)s -> ac.forAll((I<Character, Boolean>)<error descr="Incompatible return type String in lambda expression">c -> ""</error>));
         String s3 = as.forAll((II<String, String>)s -> ac.forAll((II<Character, String>)<error descr="Incompatible return type boolean in lambda expression">c -> false</error>));
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/DefaultMethodOverrideEquivalentObject.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/DefaultMethodOverrideEquivalentObject.java
index cb671b7..84b2259 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/DefaultMethodOverrideEquivalentObject.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/DefaultMethodOverrideEquivalentObject.java
@@ -2,4 +2,5 @@
     default String <error descr="Default method 'toString' overrides a member of 'java.lang.Object'">toString</error>() {
         return "";
     }
+    default void finalize() throws Throwable { }
 }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/AccessModifiers.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/AccessModifiers.java
index 40811fd..bc235b2 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/AccessModifiers.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/AccessModifiers.java
@@ -29,7 +29,7 @@
         <error descr="Incompatible types. Found: '<method reference>', required: 'AlienTest.IInt'">IInt i2 = MyTest::foo;</error>
         <error descr="Incompatible types. Found: '<method reference>', required: 'AlienTest.IInt'">IInt i3 = MyTest::bar;</error>
         <error descr="Incompatible types. Found: '<method reference>', required: 'AlienTest.IIntInt'">IIntInt i4 = MyTest::bar;</error>
-        <error descr="Incompatible types. Found: '<method reference>', required: 'AlienTest.IInt'">IInt i5 = MyTest::baz;</error>
+        IInt i5 = <error descr="Non-static method cannot be referenced from a static context">MyTest::baz</error>;
         IInt i6 = <error descr="'foo(int)' is not public in 'MyTest.Foo'. Cannot be accessed from outside package">MyTest.foo::foo</error>;
         IInt i7 = MyTest.<error descr="'MyTest.Foo' has private access in 'MyTest'">Foo</error>::foo;
     }
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java
index 848c423..0696aad 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java
@@ -29,7 +29,7 @@
     }
 
     public static void main(String[] args) {
-        foo<error descr="Ambiguous method call: both 'MyTest.foo(I1)' and 'MyTest.foo(I2)' match">(Foo::m)</error>;
+        foo<error descr="Ambiguous method call: both 'MyTest.foo(I2)' and 'MyTest.foo(I3)' match">(Foo::m)</error>;
     }
 }
 
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/StaticProblems.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/StaticProblems.java
index 3375ceb..8d482f2 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/StaticProblems.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/StaticProblems.java
@@ -41,14 +41,14 @@
     static void call2(I2 s) {   }
 
     static void test1() {
-        <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest1.I1'">I1 s1 = MyTest1 ::m1;</error>
-        call1<error descr="'call1(MyTest1.I1)' in 'MyTest1' cannot be applied to '(<method reference>)'">(MyTest1::m1)</error>;
+        I1 s1 = <error descr="Non-static method cannot be referenced from a static context">MyTest1 ::m1</error>;
+        call1(<error descr="Non-static method cannot be referenced from a static context">MyTest1::m1</error>);
         I1 s2 = MyTest1  :: m2;
         call1(MyTest1::m2);
         I1 s3 = MyTest1::m3;
         call1(MyTest1::m3);
-        <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest1.I1'">I1 s4 = MyTest1::m4;</error>
-        call1<error descr="'call1(MyTest1.I1)' in 'MyTest1' cannot be applied to '(<method reference>)'">(MyTest1::m4)</error>;
+        I1 s4 = <error descr="Non-static method cannot be referenced from a static context">MyTest1::m4</error>;
+        call1(<error descr="Non-static method cannot be referenced from a static context">MyTest1::m4</error>);
     }
 
     static void test2() {
@@ -90,14 +90,14 @@
     static void call2(I2 s) {   }
 
     static void test1() {
-        <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest2.I1'">I1 s1 = MyTest2 ::m1;</error>
-        call1<error descr="'call1(MyTest2.I1)' in 'MyTest2' cannot be applied to '(<method reference>)'">(MyTest2::m1)</error>;
+        I1 s1 = <error descr="Non-static method cannot be referenced from a static context">MyTest2 ::m1</error>;
+        call1(<error descr="Non-static method cannot be referenced from a static context">MyTest2::m1</error>);
         I1 s2 = MyTest2  :: m2;
         call1(MyTest2::m2);
         I1 s3 = MyTest2::m3;
         call1(MyTest2::m3);
-        <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest2.I1'">I1 s4 = MyTest2::m4;</error>
-        call1<error descr="'call1(MyTest2.I1)' in 'MyTest2' cannot be applied to '(<method reference>)'">(MyTest2::m4)</error>;
+        I1 s4 = <error descr="Non-static method cannot be referenced from a static context">MyTest2::m4</error>;
+        call1(<error descr="Non-static method cannot be referenced from a static context">MyTest2::m4</error>);
     }
 
     static void test2() {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/Varargs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/Varargs.java
index 66f4e07..e521df2 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/Varargs.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/Varargs.java
@@ -55,7 +55,7 @@
 
 
     {
-        <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest.I1'">I1 i_1 = MyTest::_1;</error>
+        I1 i_1 = <error descr="Non-static method cannot be referenced from a static context">MyTest::_1</error>;
         <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest.I1'">I1 i_2 = MyTest::_2;</error>
         <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest.I1'">I1 i_3 = MyTest::_3;</error>
         <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest.I1'">I1 i_4 = MyTest::_4;</error>
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/VarargsInReceiverPosition.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/VarargsInReceiverPosition.java
index f6c1e3f..cf2151d 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/VarargsInReceiverPosition.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/VarargsInReceiverPosition.java
@@ -3,7 +3,7 @@
 class Test {
     void test() {
         Comparator<Test> r2 = Test::yyy;
-        <error descr="Incompatible types. Found: '<method reference>', required: 'Comparator1<Test>'">Comparator1<Test> c1 = Test::yyy;</error>
+        Comparator1<Test> c1 = <error descr="Non-static method cannot be referenced from a static context">Test::yyy</error>;
         <error descr="Incompatible types. Found: '<method reference>', required: 'Comparator1<Test>'">Comparator1<Test> c2 = Test::xxx;</error>
     }
     int yyy(Test... p) { return 1; }
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/DiamondInLambdaReturn.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/DiamondInLambdaReturn.java
new file mode 100644
index 0000000..8f547d2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/DiamondInLambdaReturn.java
@@ -0,0 +1,9 @@
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+class Test {
+  Set<String> collect(Stream<String> map){
+    return map.collect(Collectors.toCollection(() -> new LinkedHashSet<>()));
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA118965.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA118965.java
new file mode 100644
index 0000000..207a091
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA118965.java
@@ -0,0 +1,37 @@
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static java.util.Arrays.asList;
+
+class Test {
+
+  public static void main(String[] args) {
+
+    List<String> list = new ArrayList<>(); // JDK 7 diamond operator
+    list.add("aaa");
+    list.add("bb");
+    list.add("cccc");
+    list.add("dd");
+    list.add("e");
+
+    schwartz(list.stream(), s -> s.length())
+      .forEach(x -> { System.out.println(x); });
+  }
+
+  public static<T, R extends Comparable<? super R>> Stream<T> schwartz(Stream<T> stream, Function<T, R> f) {
+
+    // class Pair - type of second element of pair must be Comparable
+    final class Pair<F, S extends Comparable<? super S>> {
+      public final F first;
+      public final S second;
+      public Pair(F first, S second){ this.first = first; this.second = second; }
+    }
+
+    return stream
+      .map(t -> new Pair<>(t, f.apply(t)))
+      .sorted((p1, p2) -> p1.second.compareTo(p2.second))
+      .map(p -> p.first);
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java
index ab7614c..18f5026 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java
@@ -53,7 +53,7 @@
         Test s1 = staticCall(Test::n0);
         Test s2 = staticCall(Test::n1);
         Test s3 = staticCall<error descr="Cannot resolve method 'staticCall(<method reference>)'">(Test::n2)</error>;
-        Test s4 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Test>)' and 'Test.staticCall(I2<Test,String>)' match">(Test::n01)</error>;
-        Test s5 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Test>)' and 'Test.staticCall(I2<Test,String>)' match">(Test::n012)</error>;
+        Test s4 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Test>)' and 'Test.staticCall(I2<Test, String>)' match">(Test::n01)</error>;
+        Test s5 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<Test>)' and 'Test.staticCall(I2<Test, String>)' match">(Test::n012)</error>;
     }
 }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/ReturnTypeCheckForRawReceiver.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/ReturnTypeCheckForRawReceiver.java
new file mode 100644
index 0000000..853b02a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/ReturnTypeCheckForRawReceiver.java
@@ -0,0 +1,15 @@
+class Test {
+
+  static class Foo<X> {
+    X m() { return null;}
+  }
+
+  interface I {
+    Foo<Object> _i(Foo<String> fs);
+  }
+
+  static void foo(I i) { }
+  {
+    foo(<error descr="Bad return type in method reference: cannot convert java.lang.String to Test.Foo<java.lang.Object>">Foo::m</error>);
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/StaticNonStaticReferenceTypeAmbiguity.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/StaticNonStaticReferenceTypeAmbiguity.java
new file mode 100644
index 0000000..7430c7c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/StaticNonStaticReferenceTypeAmbiguity.java
@@ -0,0 +1,15 @@
+class Test {
+
+  interface I {
+    void m(Test rec, String s);
+  }
+
+  void m(Test t, String s) {}
+  void m(String s) {}
+
+  static void m(Test t, Object s) {}
+
+  static void test() {
+    <error descr="Incompatible types. Found: '<method reference>', required: 'Test.I'">I i = Test::m;</error>
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/LambdaFormalParamTypesParametrization.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/LambdaFormalParamTypesParametrization.java
new file mode 100644
index 0000000..0dbcc3e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/LambdaFormalParamTypesParametrization.java
@@ -0,0 +1,10 @@
+import java.util.function.Function;
+
+class Test {
+
+  <U, V> void foo(Function<U, ? extends V> m) {}
+
+  {
+    foo((String e) -> e.length());
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/NonWildcardParametrization.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/NonWildcardParametrization.java
new file mode 100644
index 0000000..fa9df55
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/NonWildcardParametrization.java
@@ -0,0 +1,108 @@
+import java.util.List;
+
+class SimpleDependency  {
+
+  interface I<R extends U, U> {
+    R m();
+  }
+
+  {
+    I<? extends String, ? extends  String> k = () -> null;
+    I<? extends String, String> k1 = () -> null;
+    I<? extends List<String>, List<String>> k2 = () -> null;
+    I<? extends List<String>, ? extends List<String>> k3 = () -> null;
+    I<? extends List<? extends String>, ? extends List<String>> k4 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends List<? extends String>, List<? extends String>> k5 = () -> null;
+    I<? extends List<? extends String>, ? extends List<? extends String>> k6 = () -> null;
+
+    I<? super String, String> s = () -> null;
+    I<? super List<String>, List<? extends String>> s1 = () -> null;
+  }
+}
+
+class NoDependency {
+  interface I<T, U> {
+    T m();
+  }
+
+  {
+    I<? extends String, ? extends String> k = () -> null;
+  }
+}
+
+class ExtendsList {
+  interface I<R extends List<T>, T> {
+    R m();
+  }
+
+  {
+    I<?, ? extends String> n = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<?, ?> n1 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<?, String> n2 = <error descr="Cannot infer functional interface type">() -> null</error>;
+
+
+    I<? extends List<?>, String> e1 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends List<?>, ?> e2 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends List<String>, ? extends String> e3 = () -> null;
+    I<? extends List<? extends String>, ? extends String> e4 = <error descr="Cannot infer functional interface type">() -> null</error>;
+
+    I<? super List<String>, ? extends String> s1 = () -> null;
+    I<? super List<String>, String> s2 = () -> null;
+  }
+}
+
+class MultipleBounds {
+  interface I<R extends List<T> & Comparable<T>, T> {
+    R m();
+  }
+
+  interface LC<K> extends List<K>, Comparable<K> {}
+
+  {
+    I<?, String> n = <error descr="Cannot infer functional interface type">() -> null</error>;
+
+    I<? extends List<String>, ? extends String> e1 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends Comparable<String>, ? extends String> e2 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends LC<String>, ? extends String> e3 = () -> null;
+    I<? extends LC<String>, String> e4 = () -> null;
+    I<? extends LC<? extends String>, String> e5 = <error descr="Cannot infer functional interface type">() -> null</error>;
+  }
+}
+
+class FirstIndependentBound {
+  interface I<R extends List<String> & Comparable<T>, T> {
+    R m();
+  }
+
+  interface LC<K> extends List<String>, Comparable<K> {}
+
+  {
+    I<?, String> n = <error descr="Cannot infer functional interface type">() -> null</error>;
+
+    I<? extends List<String>, ? extends String> e1 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends Comparable<String>, ? extends String> e2 = () -> null;
+    I<? extends LC<String>, ? extends String> e3 = () -> null;
+    I<? extends LC<String>, String> e4 = () -> null;
+    I<? extends LC<? extends String>, String> e5 = <error descr="Cannot infer functional interface type">() -> null</error>;
+  }
+}
+
+
+class SecondIndependentBound {
+  interface I<R extends List<T> & Comparable<String>, T> {
+    R m();
+  }
+
+  interface LC<K> extends List<String>, Comparable<K> {}
+
+  {
+    I<?, String> n = <error descr="Cannot infer functional interface type">() -> null</error>;
+
+    I<? extends List<String>, ? extends String> e1 = () -> null;
+    I<? extends Comparable<String>, ? extends String> e2 = <error descr="Cannot infer functional interface type">() -> null</error>;
+    I<? extends LC<String>, ? extends String> e3 = () -> null;
+    I<? extends LC<String>, String> e4 = () -> null;
+    I<? extends LC<? extends String>, String> e5 = <error descr="Cannot infer functional interface type">()  -> null</error>;
+    I<? extends LC<? extends String>, ? extends String> e6 = <error descr="Cannot infer functional interface type">()  -> null</error>;
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/PrimitiveParameterTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/PrimitiveParameterTypes.java
new file mode 100644
index 0000000..f339392
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization/PrimitiveParameterTypes.java
@@ -0,0 +1,13 @@
+class IDEA100385 {
+  void foo(N<Double> n){
+    n.forEach((<error descr="Incompatible parameter types in lambda expression">double e</error>) -> { });
+  }
+  static interface N<E> {
+    void forEach(Consumer<? extends E> consumer);
+  }
+
+  interface Consumer<T> {
+    public void accept(T t);
+  }
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterEnumConstantWithoutClassInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterEnumConstantWithoutClassInitializer.java
index 9ae8bed..2369d9c 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterEnumConstantWithoutClassInitializer.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterEnumConstantWithoutClassInitializer.java
@@ -1,9 +1,11 @@
 // "Implement Methods" "true"
 enum E {
-  A {
-      public void foo() {
-        
-      }
-  };
-  abstract void foo();
+    A {
+        @Override
+        public int foo() {
+            return 0;
+        }
+    };
+
+    public abstract int foo();
 }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterIDEA108454.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterIDEA108454.java
new file mode 100644
index 0000000..a7e8482
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterIDEA108454.java
@@ -0,0 +1,17 @@
+// "Implement Methods" "true"
+class Test {
+    class A<T> {
+        public class Inner { }
+    }
+
+    interface B<T> {
+        T foo();
+    }
+
+    class D implements B<A<String>.Inner> {
+        @Override
+        public A<String>.Inner foo() {
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeEnumConstantWithoutClassInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeEnumConstantWithoutClassInitializer.java
index 92bbb6a..518de23 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeEnumConstantWithoutClassInitializer.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeEnumConstantWithoutClassInitializer.java
@@ -1,5 +1,6 @@
 // "Implement Methods" "true"
 enum E {
-  <caret>A;
-  public abstract void foo();
+    <caret>A;
+
+    public abstract int foo();
 }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeIDEA108454.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeIDEA108454.java
new file mode 100644
index 0000000..32e8e5b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeIDEA108454.java
@@ -0,0 +1,12 @@
+// "Implement Methods" "true"
+class Test {
+    class A<T> {
+        public class Inner { }
+    }
+
+    interface B<T> {
+        T foo();
+    }
+
+    <caret>class D implements B<A<String>.Inner> { }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectArrayList.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectArrayList.java
new file mode 100644
index 0000000..aef9e75
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectArrayList.java
@@ -0,0 +1,15 @@
+// "Replace with collect" "true"
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    List<String> names = persons.stream().map(Person::getName).collect(Collectors.toList());
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectArrayListAndFilter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectArrayListAndFilter.java
new file mode 100644
index 0000000..4467078
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectArrayListAndFilter.java
@@ -0,0 +1,15 @@
+// "Replace with collect" "true"
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    List<String> names = persons.stream().filter(person -> person != null).map(Person::getName).collect(Collectors.toList());
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectArrayListLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectArrayListLambda.java
new file mode 100644
index 0000000..e151774
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectArrayListLambda.java
@@ -0,0 +1,15 @@
+// "Replace with collect" "true"
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    List<String> names = persons.stream().map(person -> "name: " + person.getName()).collect(Collectors.toList());
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectHashSet.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectHashSet.java
new file mode 100644
index 0000000..022b8e3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectHashSet.java
@@ -0,0 +1,15 @@
+// "Replace with collect" "true"
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    Set<String> names = persons.stream().map(Person::getName).collect(Collectors.toSet());
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectHashSetFieldInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectHashSetFieldInitializer.java
new file mode 100644
index 0000000..edd903a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectHashSetFieldInitializer.java
@@ -0,0 +1,16 @@
+// "Replace with collect" "true"
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  Set<String> names = new HashSet<>();
+  void collectNames(List<Person> persons){
+      names.addAll(persons.stream().map(Person::getName).collect(Collectors.toList()));
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectLinkedHashSet.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectLinkedHashSet.java
new file mode 100644
index 0000000..6bb6839
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectLinkedHashSet.java
@@ -0,0 +1,15 @@
+// "Replace with collect" "true"
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    Set<String> names = persons.stream().map(Person::getName).collect(Collectors.toCollection(() -> new LinkedHashSet<>()));
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectSelfCollection.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectSelfCollection.java
new file mode 100644
index 0000000..676c127
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectSelfCollection.java
@@ -0,0 +1,15 @@
+// "Replace with collect" "true"
+import java.util.*;
+import java.util.stream.Collectors;
+
+public abstract class Collect implements Collection<String>{
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+      addAll(persons.stream().map(Person::getName).collect(Collectors.toList()));
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectSetParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectSetParameter.java
new file mode 100644
index 0000000..c8201c9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterCollectSetParameter.java
@@ -0,0 +1,15 @@
+// "Replace with collect" "true"
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons, Set<String> names){
+      names.addAll(persons.stream().map(Person::getName).collect(Collectors.toList()));
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFilterNoBraces.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFilterNoBraces.java
new file mode 100644
index 0000000..ab67b49
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterFilterNoBraces.java
@@ -0,0 +1,10 @@
+// "Replace with forEach" "true"
+import java.util.ArrayList;
+import java.util.List;
+
+class Sample {
+  List<String> foo = new ArrayList<>();
+  {
+      foo.stream().filter(s -> s != null).forEach(System.out::println);
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterNormalNoBraces.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterNormalNoBraces.java
new file mode 100644
index 0000000..b7c6bde
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/afterNormalNoBraces.java
@@ -0,0 +1,10 @@
+// "Replace with forEach" "true"
+import java.util.ArrayList;
+import java.util.List;
+
+class Sample {
+  List<String> foo = new ArrayList<>();
+  {
+      foo.forEach(System.out::println);
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectArrayList.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectArrayList.java
new file mode 100644
index 0000000..3114dd7
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectArrayList.java
@@ -0,0 +1,17 @@
+// "Replace with collect" "true"
+import java.util.*;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    List<String> names = new ArrayList<>();
+    for (Person person : pers<caret>ons) {
+      names.add(person.getName());
+    }
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectArrayListAndFilter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectArrayListAndFilter.java
new file mode 100644
index 0000000..9a671cb
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectArrayListAndFilter.java
@@ -0,0 +1,19 @@
+// "Replace with collect" "true"
+import java.util.*;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    List<String> names = new ArrayList<>();
+    for (Person person : pers<caret>ons) {
+      if (person != null) {
+        names.add(person.getName());
+      }
+    }
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectArrayListLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectArrayListLambda.java
new file mode 100644
index 0000000..434c2c5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectArrayListLambda.java
@@ -0,0 +1,17 @@
+// "Replace with collect" "true"
+import java.util.*;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    List<String> names = new ArrayList<>();
+    for (Person person : pers<caret>ons) {
+      names.add("name: " + person.getName());
+    }
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectHashSet.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectHashSet.java
new file mode 100644
index 0000000..9e1e0e5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectHashSet.java
@@ -0,0 +1,17 @@
+// "Replace with collect" "true"
+import java.util.*;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    Set<String> names = new HashSet<>();
+    for (Person person : pers<caret>ons) {
+      names.add(person.getName());
+    }
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectHashSetFieldInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectHashSetFieldInitializer.java
new file mode 100644
index 0000000..44f39e1
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectHashSetFieldInitializer.java
@@ -0,0 +1,17 @@
+// "Replace with collect" "true"
+import java.util.*;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  Set<String> names = new HashSet<>();
+  void collectNames(List<Person> persons){
+    for (Person person : pers<caret>ons) {
+      names.add(person.getName());
+    }
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectLinkedHashSet.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectLinkedHashSet.java
new file mode 100644
index 0000000..f3ffecc
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectLinkedHashSet.java
@@ -0,0 +1,17 @@
+// "Replace with collect" "true"
+import java.util.*;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    Set<String> names = new LinkedHashSet<>();
+    for (Person person : pers<caret>ons) {
+      names.add(person.getName());
+    }
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectSelfCollection.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectSelfCollection.java
new file mode 100644
index 0000000..1dbed31
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectSelfCollection.java
@@ -0,0 +1,16 @@
+// "Replace with collect" "true"
+import java.util.*;
+
+public abstract class Collect implements Collection<String>{
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons){
+    for (Person person : pers<caret>ons) {
+      add(person.getName());
+    }
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectSetParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectSetParameter.java
new file mode 100644
index 0000000..f7287c4
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeCollectSetParameter.java
@@ -0,0 +1,16 @@
+// "Replace with collect" "true"
+import java.util.*;
+
+public class Collect {
+  class Person {
+    String getName() {
+      return "";
+    }
+  }
+
+  void collectNames(List<Person> persons, Set<String> names){
+    for (Person person : pers<caret>ons) {
+      names.add(person.getName());
+    }
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeFilterNoBraces.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeFilterNoBraces.java
new file mode 100644
index 0000000..8c71276
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeFilterNoBraces.java
@@ -0,0 +1,12 @@
+// "Replace with forEach" "true"
+import java.util.ArrayList;
+import java.util.List;
+
+class Sample {
+  List<String> foo = new ArrayList<>();
+  {
+    for (String s : fo<caret>o) {
+      if (s != null) System.out.println(s);
+    }
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeNormalNoBraces.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeNormalNoBraces.java
new file mode 100644
index 0000000..0ad9844
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeNormalNoBraces.java
@@ -0,0 +1,10 @@
+// "Replace with forEach" "true"
+import java.util.ArrayList;
+import java.util.List;
+
+class Sample {
+  List<String> foo = new ArrayList<>();
+  {
+    for (String s : fo<caret>o) System.out.println(s);
+  }
+}
diff --git a/java/java-tests/testData/codeInsight/gotosuper/Lambda.after.java b/java/java-tests/testData/codeInsight/gotosuper/Lambda.after.java
new file mode 100644
index 0000000..2fe10c2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/gotosuper/Lambda.after.java
@@ -0,0 +1,9 @@
+interface I {
+  void <caret>run();
+}
+
+class Foo {
+  {
+    I i = () -> {};
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/gotosuper/Lambda.java b/java/java-tests/testData/codeInsight/gotosuper/Lambda.java
new file mode 100644
index 0000000..26c0243
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/gotosuper/Lambda.java
@@ -0,0 +1,9 @@
+interface I {
+  void run();
+}
+
+class Foo {
+  {
+    I i = ()<caret> -> {};
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/gotosuper/LambdaMarker.java b/java/java-tests/testData/codeInsight/gotosuper/LambdaMarker.java
new file mode 100644
index 0000000..26c0243
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/gotosuper/LambdaMarker.java
@@ -0,0 +1,9 @@
+interface I {
+  void run();
+}
+
+class Foo {
+  {
+    I i = ()<caret> -> {};
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/fileEditorManager/src/Bar.java b/java/java-tests/testData/fileEditorManager/src/Bar.java
new file mode 100644
index 0000000..4843c68
--- /dev/null
+++ b/java/java-tests/testData/fileEditorManager/src/Bar.java
@@ -0,0 +1,5 @@
+public class Bar {
+    public String doIt() {
+        return "";
+    }
+}
diff --git a/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef.java b/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef.java
index b068876..ded427d 100644
--- a/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef.java
+++ b/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef.java
@@ -1,15 +1,12 @@
-import java.lang.annotation.*;
-import static java.lang.annotation.ElementType.*;
-
-@Target({TYPE_USE}) @interface TA { }
+import pkg.TA;
 
 class Outer {
   class Middle {
     class Inner {
       void m1(Outer.Middle.Inner p) { }
-      void m2(@TA Outer.Middle.Inner p) { }
-      void m3(Outer.@TA Middle.Inner p) { }
-      void m4(Outer.Middle.@TA @TA Inner p) { }
+      void m2(@pkg.TA Outer.Middle.Inner p) { }
+      void m3(Outer.@pkg.TA Middle.Inner p) { }
+      void m4(Outer.Middle.@pkg.TA @pkg.TA Inner p) { }
     }
   }
 }
diff --git a/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef_after.java b/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef_after.java
index 1c4c8d4..fab10a3 100644
--- a/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef_after.java
+++ b/java/java-tests/testData/psi/shortenClassRefs/TypeAnnotatedRef_after.java
@@ -1,7 +1,4 @@
-import java.lang.annotation.*;
-import static java.lang.annotation.ElementType.*;
-
-@Target({TYPE_USE}) @interface TA { }
+import pkg.TA;
 
 class Outer {
   class Middle {
diff --git a/java/java-tests/testData/psi/shortenClassRefs/pkg/TA.java b/java/java-tests/testData/psi/shortenClassRefs/pkg/TA.java
new file mode 100644
index 0000000..abe2aca
--- /dev/null
+++ b/java/java-tests/testData/psi/shortenClassRefs/pkg/TA.java
@@ -0,0 +1,6 @@
+package pkg;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE_USE})
+@interface TA { }
diff --git a/java/java-tests/testData/refactoring/introduceVariable/genericWithTwoParameters/after/Client.java b/java/java-tests/testData/refactoring/introduceVariable/genericWithTwoParameters/after/Client.java
index 38d94b3..c98b7fa 100644
--- a/java/java-tests/testData/refactoring/introduceVariable/genericWithTwoParameters/after/Client.java
+++ b/java/java-tests/testData/refactoring/introduceVariable/genericWithTwoParameters/after/Client.java
@@ -2,6 +2,6 @@
 
 class Client {
     void method() {
-        Pair<String, Pair<Integer,Boolean>> p = PairProvider.getPair();
+        Pair<String, Pair<Integer, Boolean>> p = PairProvider.getPair();
     }
 }
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/AddAnnotationFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/AddAnnotationFixTest.java
index 231a0cd..ec8b8dd 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/AddAnnotationFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/AddAnnotationFixTest.java
@@ -27,7 +27,6 @@
 import com.intellij.openapi.application.Result;
 import com.intellij.openapi.application.ex.PathManagerEx;
 import com.intellij.openapi.command.WriteCommandAction;
-import com.intellij.openapi.editor.CaretModel;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.module.Module;
@@ -51,6 +50,7 @@
 import com.intellij.testFramework.UsefulTestCase;
 import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
 import com.intellij.testFramework.fixtures.*;
+import com.intellij.util.ObjectUtils;
 import com.intellij.util.messages.MessageBusConnection;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -122,13 +122,7 @@
 
   @NotNull
   private PsiModifierListOwner getOwner() {
-    CaretModel caretModel = myFixture.getEditor().getCaretModel();
-    int position = caretModel.getOffset();
-    PsiElement element = myFixture.getFile().findElementAt(position);
-    assert element != null;
-    PsiModifierListOwner container = AddAnnotationPsiFix.getContainer(element);
-    assert container != null;
-    return container;
+    return ObjectUtils.assertNotNull(AddAnnotationPsiFix.getContainer(myFixture.getFile(), myFixture.getCaretOffset()));
   }
 
   private void startListening(@NotNull final List<Trinity<PsiModifierListOwner, String, Boolean>> expectedSequence) {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/ImplementMethodsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/ImplementMethodsTest.java
index b5ab59a..6fd6553 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/ImplementMethodsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/ImplementMethodsTest.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.
@@ -15,13 +15,12 @@
  */
 package com.intellij.codeInsight;
 
-import com.intellij.codeInsight.daemon.quickFix.LightQuickFixAvailabilityTestCase;
+import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
 
 /**
- * User: anna
- * Date: 10/7/11
+ * @author anna
  */
-public class ImplementMethodsTest extends LightQuickFixAvailabilityTestCase {
+public class ImplementMethodsTest extends LightQuickFixParameterizedTestCase {
   public void test() throws Exception {
     doAllTests();
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
index 4e8961d..0b12b54 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
@@ -52,6 +52,7 @@
 import com.intellij.psi.PsiJavaFile
 import com.intellij.psi.statistics.StatisticsManager
 import com.intellij.psi.statistics.impl.StatisticsManagerImpl
+import com.intellij.testFramework.EditorTestUtil
 import com.intellij.util.containers.ContainerUtil
 import org.jetbrains.annotations.NotNull
 
@@ -1141,6 +1142,56 @@
 }}'''
   }
 
+  public void testMulticaret() {
+    doTestMulticaret """
+class Foo {{
+  <selection>t<caret></selection>x;
+  <selection>t<caret></selection>x;
+}}""", '\n', '''
+class Foo {{
+  toString()<caret>x;
+  toString()<caret>x;
+}}'''
+  }
+
+  public void testMulticaretTab() {
+    doTestMulticaret """
+class Foo {{
+  <selection>t<caret></selection>x;
+  <selection>t<caret></selection>x;
+}}""", '\t', '''
+class Foo {{
+  toString()<caret>;
+  toString()<caret>;
+}}'''
+  }
+
+  public void testMulticaretBackspace() {
+    doTestMulticaret """
+class Foo {{
+  <selection>t<caret></selection>;
+  <selection>t<caret></selection>;
+}}""", '\b\t', '''
+class Foo {{
+  toString()<caret>;
+  toString()<caret>;
+}}'''
+  }
+
+  private doTestMulticaret(final String textBefore, final String toType, final String textAfter) {
+    EditorTestUtil.enableMultipleCarets()
+    try {
+      myFixture.configureByText "a.java", textBefore
+      type 'toStr'
+      assert lookup
+      type toType
+      myFixture.checkResult textAfter
+    }
+    finally {
+      EditorTestUtil.disableMultipleCarets()
+    }
+  }
+
   private doTestBlockSelection(final String textBefore, final String toType, final String textAfter) {
     myFixture.configureByText "a.java", textBefore
     edt {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
index f07a963..35b71f8 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
@@ -1403,6 +1403,33 @@
     }
   }
 
+  public void testPrimitiveSquareBracketWhenMultipleCaretsAreEnabled() {
+    EditorTestUtil.enableMultipleCarets()
+    try {
+      configureByFile("PrimitiveSquareBracket.java");
+      type('[');
+      checkResultByFile("PrimitiveSquareBracket_after.java");
+    }
+    finally {
+      EditorTestUtil.disableMultipleCarets()
+    }
+  }
+
+  public void testMulticaretTyping() {
+    EditorTestUtil.enableMultipleCarets()
+    try {
+      configure()
+      assert lookup
+      type('p')
+      assert lookup
+      type('\n')
+      checkResult()
+    }
+    finally {
+      EditorTestUtil.disableMultipleCarets()
+    }
+  }
+
   public void "test complete lowercase class name"() {
     myFixture.addClass("package foo; public class myClass {}")
     myFixture.configureByText "a.java", """
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java
index 1868d21..964566f 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java
@@ -39,6 +39,8 @@
   public void testInapplicable() { doTest(false); }
   public void testDuplicateAttribute() { doTest(false); }
   public void testDuplicateTarget() { doTest(false); }
+  public void testPingPongAnnotationTypesDependencies() { doTest(false);}
+  public void testClashMethods() { doTest(false);}
 
   public void testInvalidPackageAnnotationTarget() { doTest(BASE_PATH + "/" + getTestName(true) + "/package-info.java", false, false); }
   public void testPackageAnnotationNotInPackageInfo() { doTest(BASE_PATH + "/" + getTestName(true) + "/notPackageInfo.java", false, false); }
@@ -46,9 +48,6 @@
   public void testTypeAnnotations() { doTest8(false); }
   public void testRepeatable() { doTest8(false); }
 
-  public void testPingPongAnnotationTypesDependencies() { doTest(false);}
-  public void testClashMethods() { doTest(false);}
-
   private void doTest(boolean checkWarnings) {
     setLanguageLevel(LanguageLevel.JDK_1_7);
     doTest(BASE_PATH + "/" + getTestName(true) + ".java", checkWarnings, false);
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ImportHelperTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ImportHelperTest.java
index b50052b..80448f9 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ImportHelperTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ImportHelperTest.java
@@ -368,7 +368,7 @@
 
 
   public void testAutoImportOfGenericReference() throws Throwable {
-    @NonNls final String text = "class S {{ new ArrayList<caret><> }}";
+    @NonNls final String text = "class S {{ new ArrayList<caret><String> }}";
     configureByText(StdFileTypes.JAVA, text);
     boolean old = CodeInsightSettings.getInstance().ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY;
     CodeInsightSettings.getInstance().ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY = true;
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalTypeWildcardParameterizationTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalTypeWildcardParameterizationTest.java
new file mode 100644
index 0000000..599ae74
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalTypeWildcardParameterizationTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.lambda;
+
+import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
+import com.intellij.openapi.projectRoots.JavaSdkVersion;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.testFramework.IdeaTestUtil;
+import org.jetbrains.annotations.NonNls;
+
+public class FunctionalTypeWildcardParameterizationTest extends LightDaemonAnalyzerTestCase {
+  @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/wildcardParametrization";
+
+  public void testNonWildcardParametrization() throws Exception {
+    doTest();
+  }
+
+  public void testLambdaFormalParamTypesParametrization() throws Exception {
+    doTest();
+  }
+
+  public void testPrimitiveParameterTypes() throws Exception {
+    doTest();
+  }
+
+  private void doTest() {
+    IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable());
+    doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
+  }
+
+  @Override
+  protected Sdk getProjectJDK() {
+    return IdeaTestUtil.getMockJdk18();
+  }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
index 1119a0d..8af0821 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
@@ -28,7 +28,7 @@
     doTest();
   }
 
-  public void _testNestedCallsSameMethod() throws Exception {
+  public void testNestedCallsSameMethod() throws Exception {
     doTest();
   }
 
@@ -160,6 +160,14 @@
     doTest();
   }
 
+  public void testLiftedCaptureToOuterCall() throws Exception {
+    doTest();
+  }
+
+  public void testSiteSubstitutionForReturnConstraint() throws Exception {
+    doTest();
+  }
+
   private void doTest() throws Exception {
     doTest(false);
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
index 89ddef2..826193c 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
@@ -138,6 +138,14 @@
     doTest();
   }
 
+  public void testDiamondInLambdaReturn() throws Exception {
+    doTest();
+  }
+
+  public void testIDEA118965() throws Exception {
+    doTest();
+  }
+
   private void doTest() {
     doTest(false);
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java
index e944269..83f0dfa 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java
@@ -173,6 +173,14 @@
     doTest();
   }
 
+  public void testReturnTypeCheckForRawReceiver() throws Exception {
+    doTest();
+  }
+
+  public void testStaticNonStaticReferenceTypeAmbiguity() throws Exception {
+    doTest();
+  }
+
   private void doTest() {
     doTest(false);
   }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/navigation/JavaGotoSuperTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/navigation/JavaGotoSuperTest.java
new file mode 100644
index 0000000..3137204
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/navigation/JavaGotoSuperTest.java
@@ -0,0 +1,52 @@
+package com.intellij.codeInsight.navigation;
+
+import com.intellij.JavaTestUtil;
+import com.intellij.codeInsight.CodeInsightActionHandler;
+import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
+import com.intellij.codeInsight.daemon.LineMarkerInfo;
+import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
+import com.intellij.lang.CodeInsightActions;
+import com.intellij.lang.java.JavaLanguage;
+import com.intellij.openapi.editor.Document;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase {
+  @NotNull
+  @Override
+  protected String getTestDataPath() {
+    return JavaTestUtil.getJavaTestDataPath();
+  }
+
+  protected String getBasePath() {
+    return "/codeInsight/gotosuper/";
+  }
+
+  public void testLambda() throws Throwable {
+    doTest();
+  }
+
+  public void testLambdaMarker() throws Exception {
+    configureByFile(getBasePath() + getTestName(false) + ".java");
+    int offset = myEditor.getCaretModel().getOffset();
+
+    doHighlighting();
+    Document document = getEditor().getDocument();
+    List<LineMarkerInfo> markers = DaemonCodeAnalyzerImpl.getLineMarkers(document, getProject());
+    for (LineMarkerInfo info : markers) {
+      if (info.endOffset >= offset && info.startOffset <= offset) {
+        assertEquals("<html><body>Overrides method in 'I'</body></html>", info.getLineMarkerTooltip());
+        return;
+      }
+    }
+    fail("Gutter expected");
+  }
+
+  private void doTest() throws Throwable {
+    configureByFile(getBasePath() + getTestName(false) + ".java");
+    final CodeInsightActionHandler handler = CodeInsightActions.GOTO_SUPER.forLanguage(JavaLanguage.INSTANCE);
+    handler.invoke(getProject(), getEditor(), getFile());
+    checkResultByFile(getBasePath() + getTestName(false) + ".after.java");
+  }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy
index f186f9e..6373bc3 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy
@@ -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.
@@ -15,15 +15,22 @@
  */
 package com.intellij.codeInsight.psi
 
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiFile
+import com.intellij.pom.java.LanguageLevel
+import com.intellij.psi.*
+import com.intellij.psi.impl.source.PsiImmediateClassType
 import com.intellij.testFramework.LightIdeaTestCase
 
-@SuppressWarnings(["GrUnresolvedAccess", "GroovyAssignabilityCheck"])
+@SuppressWarnings("GroovyAssignabilityCheck")
 class AnnotatedTypeTest extends LightIdeaTestCase {
+  private PsiFile context
+  private PsiElementFactory factory
 
-  public void testTypeComposition() {
-    PsiFile context = createFile("typeCompositionTest.java", """
+  public void setUp() throws Exception {
+    super.setUp()
+    factory = javaFacade.elementFactory
+    context = createFile("typeCompositionTest.java", """
+package pkg;
+
 import java.lang.annotation.*;
 import static java.lang.annotation.ElementType.*;
 
@@ -33,31 +40,55 @@
 class E1 extends Exception { }
 class E2 extends Exception { }
 """)
-    PsiElement psi
-
-    psi = javaFacade.elementFactory.createStatementFromText("@A @TA(1) int @TA(2) [] a", context)
-    assertEquals("@TA(1) int @TA(2) []", psi.declaredElements[0].type.presentableText)
-
-    psi = javaFacade.elementFactory.createStatementFromText("try { } catch (@A @TA(1) E1 | @TA(2) E2 e) { }", context)
-    assertEquals("@TA(1) E1 | @TA(2) E2", psi.catchBlockParameters[0].type.presentableText)
-
-    psi = javaFacade.elementFactory.createStatementFromText("@A @TA(1) String @TA(2) [] f @TA(3) []", context)
-    assertEquals("@TA(1) String @TA(2) [] @TA(3) []", psi.declaredElements[0].type.presentableText)
-
-    psi = javaFacade.elementFactory.createStatementFromText("Class<@TA(1) ?> c", context)
-    assertEquals("Class<@TA(1) ?>", psi.declaredElements[0].type.presentableText)
-
-    psi = javaFacade.elementFactory.createStatementFromText("Class<@TA String> cs = new Class<>()", context)
-    assertEquals("Class<@TA String>", psi.declaredElements[0].initializer.type.presentableText)
-
-    psi = javaFacade.elementFactory.createStatementFromText("@A @TA(1) String s", context)
-    assertEquals("@TA(1) String", psi.declaredElements[0].type.presentableText)
-
-    psi = javaFacade.elementFactory.createStatementFromText("@A java.lang.@TA(1) String s", context)
-    assertEquals("@TA(1) String", psi.declaredElements[0].type.presentableText)
-
-    psi = javaFacade.elementFactory.createStatementFromText("Collection<? extends> s", context)
-    assertEquals("Collection<?>", psi.declaredElements[0].type.presentableText)
   }
 
+  public void testPrimitiveArrayType() {
+    doTest("@A @TA(1) int @TA(2) [] a", "@pkg.TA(1) int @pkg.TA(2) []", "int[]")
+  }
+
+  public void testEllipsisType() {
+    def psi = factory.createParameterFromText("@TA int @TA ... p", context)
+    assertTypeText(psi.type, "@pkg.TA int @pkg.TA ...", "int...")
+  }
+
+  public void testClassReferenceType() {
+    doTest("@A @TA(1) String s", "java.lang.@pkg.TA(1) String", "java.lang.String")
+    doTest("@A java.lang.@TA(1) String s", "java.lang.@pkg.TA(1) String", "java.lang.String")
+  }
+
+  public void testCStyleArrayType() {
+    doTest("@A @TA(1) String @TA(2) [] f @TA(3) []", "java.lang.@pkg.TA(1) String @pkg.TA(2) [] @pkg.TA(3) []", "java.lang.String[][]")
+  }
+
+  public void testWildcardType() {
+    doTest("Class<@TA(1) ?> c", "java.lang.Class<@pkg.TA(1) ?>", "java.lang.Class<?>")
+  }
+
+  public void testDisjunctionType() {
+    def psi = factory.createStatementFromText("try { } catch (@A @TA(1) E1 | @TA(2) E2 e) { }", context)
+    assertTypeText(psi.catchBlockParameters[0].type, "pkg.@pkg.TA(1) E1 | pkg.@pkg.TA(2) E2", "pkg.E1 | pkg.E2")
+  }
+
+  public void testDiamondType() {
+    def psi = factory.createStatementFromText("Class<@TA String> cs = new Class<>()", context)
+    assertTypeText(psi.declaredElements[0].initializer.type, "java.lang.Class<java.lang.@pkg.TA String>", "java.lang.Class<java.lang.String>")
+  }
+
+  public void testImmediateClassType() {
+    def aClass = javaFacade.findClass(CommonClassNames.JAVA_LANG_OBJECT)
+    def statement = factory.createStatementFromText("@TA int x", context)
+    def annotations = statement.declaredElements[0].modifierList.annotations
+    def type = new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY, LanguageLevel.JDK_1_8, annotations)
+    assertTypeText(type, "java.lang.@pkg.TA Object", CommonClassNames.JAVA_LANG_OBJECT)
+  }
+
+  private void doTest(String text, String annotated, String canonical) {
+    def psi = factory.createStatementFromText(text, context)
+    assertTypeText(psi.declaredElements[0].type, annotated, canonical)
+  }
+
+  private static void assertTypeText(PsiType type, String annotated, String canonical) {
+    assert type.getCanonicalText(true) == annotated
+    assert type.getCanonicalText(false) == canonical
+  }
 }
diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
index c2cef13..bfd1de7 100644
--- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
+++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
@@ -194,7 +194,7 @@
     PsiDirectory psiDirectory = FindInProjectUtil.getPsiDirectory(findModel, myProject);
     List<UsageInfo> result = new ArrayList<UsageInfo>();
     final CommonProcessors.CollectProcessor<UsageInfo> collector = new CommonProcessors.CollectProcessor<UsageInfo>(result);
-    FindInProjectUtil.findUsages(findModel, psiDirectory, myProject, true, collector, new FindUsagesProcessPresentation(FindInProjectUtil.setupViewPresentation(true, findModel)));
+    FindInProjectUtil.findUsages(findModel, psiDirectory, myProject, collector, new FindUsagesProcessPresentation(FindInProjectUtil.setupViewPresentation(true, findModel)));
     return result;
   }
 
diff --git a/java/java-tests/testSrc/com/intellij/index/IndexTest.java b/java/java-tests/testSrc/com/intellij/index/IndexTest.java
index fba5b6e..7770c5e 100644
--- a/java/java-tests/testSrc/com/intellij/index/IndexTest.java
+++ b/java/java-tests/testSrc/com/intellij/index/IndexTest.java
@@ -34,6 +34,7 @@
 import com.intellij.util.indexing.MapIndexStorage;
 import com.intellij.util.indexing.StorageException;
 import com.intellij.util.io.*;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -113,7 +114,7 @@
   private PersistentHashMap<Integer, Collection<String>> createMetaIndex(File metaIndexFile) throws IOException {
     return new PersistentHashMap<Integer, Collection<String>>(metaIndexFile, new EnumeratorIntegerDescriptor(), new DataExternalizer<Collection<String>>() {
       @Override
-      public void save(DataOutput out, Collection<String> value) throws IOException {
+      public void save(@NotNull DataOutput out, Collection<String> value) throws IOException {
         DataInputOutputUtil.writeINT(out, value.size());
         for (String key : value) {
           out.writeUTF(key);
@@ -121,7 +122,7 @@
       }
 
       @Override
-      public Collection<String> read(DataInput in) throws IOException {
+      public Collection<String> read(@NotNull DataInput in) throws IOException {
         final int size = DataInputOutputUtil.readINT(in);
         final List<String> list = new ArrayList<String>();
         for (int idx = 0; idx < size; idx++) {
diff --git a/java/java-tests/testSrc/com/intellij/index/StringIndex.java b/java/java-tests/testSrc/com/intellij/index/StringIndex.java
index a12f58f..7d2dd10 100644
--- a/java/java-tests/testSrc/com/intellij/index/StringIndex.java
+++ b/java/java-tests/testSrc/com/intellij/index/StringIndex.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.index;
 
 import com.intellij.openapi.util.Factory;
@@ -28,7 +43,7 @@
     myIndex.setInputIdToDataKeysIndex(factory);
   }
   
-  public List<String> getFilesByWord(String word) throws StorageException {
+  public List<String> getFilesByWord(@NotNull String word) throws StorageException {
     return myIndex.getData(word).toValueList();
   }
   
diff --git a/java/java-tests/testSrc/com/intellij/openapi/editor/impl/JavaFileEditorManagerTest.java b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/JavaFileEditorManagerTest.java
new file mode 100644
index 0000000..2a985b8
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/JavaFileEditorManagerTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor.impl;
+
+import com.intellij.openapi.fileEditor.FileEditorManagerTestCase;
+import com.intellij.testFramework.PlatformTestUtil;
+import org.jdom.JDOMException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class JavaFileEditorManagerTest extends FileEditorManagerTestCase {
+
+  public void testAsyncOpening() throws JDOMException, ExecutionException, InterruptedException, IOException {
+    openFiles("<component name=\"FileEditorManager\">\n" +
+              "    <leaf>\n" +
+              "      <file leaf-file-name=\"Bar.java\" pinned=\"false\" current=\"true\" current-in-tab=\"true\">\n" +
+              "        <entry file=\"file://$PROJECT_DIR$/src/Bar.java\">\n" +
+              "          <provider selected=\"true\" editor-type-id=\"text-editor\">\n" +
+              "            <state vertical-scroll-proportion=\"0.032882012\" vertical-offset=\"0\" max-vertical-offset=\"517\">\n" +
+              "              <caret line=\"1\" column=\"26\" selection-start=\"45\" selection-end=\"45\" />\n" +
+              "              <folding>\n" +
+              "                <element signature=\"e#69#70#0\" expanded=\"true\" />\n" +
+              "              </folding>\n" +
+              "            </state>\n" +
+              "          </provider>\n" +
+              "        </entry>\n" +
+              "      </file>\n" +
+              "    </leaf>\n" +
+              "  </component>");
+  }
+
+  @Override
+  protected String getTestDataPath() {
+    return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/java/java-tests/testData/fileEditorManager";
+  }
+}
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java
index 58c02ef..ab057c4 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -42,6 +42,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.EnumMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -51,13 +52,20 @@
  * @since Apr 27, 2010 6:26:29 PM
  */
 public abstract class AbstractJavaFormatterTest extends LightIdeaTestCase {
-
   @NotNull
-  public static String shiftIndentInside(@NotNull String initial, final int i, boolean shiftEmptyLines) throws IOException {
+  public static String shiftIndentInside(@NotNull String initial, final int i, boolean shiftEmptyLines) {
     StringBuilder result = new StringBuilder(initial.length());
-    LineReader reader = new LineReader(new ByteArrayInputStream(initial.getBytes()));
+    List<byte[]> lines;
+    try {
+      LineReader reader = new LineReader(new ByteArrayInputStream(initial.getBytes("UTF-8")));
+      lines = reader.readLines();
+    }
+    catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+
     boolean first = true;
-    for (byte[] line : reader.readLines()) {
+    for (byte[] line : lines) {
       try {
         if (!first) result.append('\n');
         if (line.length > 0 || shiftEmptyLines) {
@@ -75,7 +83,6 @@
 
   protected enum Action {REFORMAT, INDENT}
 
-
   public static JavaCodeStyleSettings getJavaSettings() {
     return getSettings().getRootSettings().getCustomSettings(JavaCodeStyleSettings.class);
   }
@@ -116,20 +123,15 @@
     return rootSettings.getCommonSettings(JavaLanguage.INSTANCE);
   }
 
-  //public static JavaCodeStyleSettings getJavaSettings() {
-  //  CodeStyleSettings rootSettings = CodeStyleSettingsManager.getSettings(getProject());
-  //  return rootSettings.getCustomSettings(JavaCodeStyleSettings.class);
-  //}
-  //
   public static CommonCodeStyleSettings.IndentOptions getIndentOptions() {
     return getSettings().getRootSettings().getIndentOptions(StdFileTypes.JAVA);
   }
 
-  public void doTest() throws Exception {
+  public void doTest() {
     doTest(getTestName(false) + ".java", getTestName(false) + "_after.java");
   }
 
-  public void doTest(@NonNls String fileNameBefore, @NonNls String fileNameAfter) throws Exception {
+  public void doTest(@NonNls String fileNameBefore, @NonNls String fileNameAfter) {
     doTextTest(Action.REFORMAT, loadFile(fileNameBefore), loadFile(fileNameAfter));
   }
 
@@ -137,7 +139,7 @@
     doTextTest(Action.REFORMAT, text, textAfter);
   }
 
-  public void doTextTest(@NotNull final Action action, @NotNull final String text, @NotNull String textAfter) throws IncorrectOperationException {
+  public void doTextTest(@NotNull final Action action, @NotNull String text, @NotNull String textAfter) throws IncorrectOperationException {
     final PsiFile file = createFile("A.java", text);
     final PsiDocumentManager manager = PsiDocumentManager.getInstance(getProject());
     final Document document = manager.getDocument(file);
@@ -204,7 +206,7 @@
     return document.getText();
   }
 
-  public void doMethodTest(@NonNls final String before, @NonNls final String after) throws Exception {
+  public void doMethodTest(@NonNls final String before, @NonNls final String after) {
     doTextTest(
       Action.REFORMAT,
       "class Foo{\n" + "    void foo() {\n" + before + '\n' + "    }\n" + "}",
@@ -212,7 +214,7 @@
     );
   }
 
-  public void doClassTest(@NonNls final String before, @NonNls final String after) throws Exception {
+  public void doClassTest(@NonNls final String before, @NonNls final String after) {
     doTextTest(
       Action.REFORMAT,
       "class Foo{\n" + before + '\n' + "}",
@@ -220,10 +222,14 @@
     );
   }
 
-  private static String loadFile(String name) throws Exception {
+  private static String loadFile(String name) {
     String fullName = BASE_PATH + File.separatorChar + name;
-    String text = FileUtil.loadFile(new File(fullName));
-    text = StringUtil.convertLineSeparators(text);
-    return text;
+    try {
+      String text = FileUtil.loadFile(new File(fullName));
+      return StringUtil.convertLineSeparators(text);
+    }
+    catch (IOException e) {
+      throw new RuntimeException(e);
+    }
   }
 }
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterNewLineTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterNewLineTest.java
index 038b1d0..a7473f6 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterNewLineTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterNewLineTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
  */
 public class JavaFormatterNewLineTest extends AbstractJavaFormatterTest {
 
-  public void testAutomaticElseWrapping() throws Exception {
+  public void testAutomaticElseWrapping() {
     getSettings().ELSE_ON_NEW_LINE = true;
 
     doMethodTest(
@@ -43,7 +43,7 @@
     );
   }
 
-  public void testAutomaticElseUnwrapping() throws Exception {
+  public void testAutomaticElseUnwrapping() {
     getSettings().ELSE_ON_NEW_LINE = false;
     getSettings().KEEP_LINE_BREAKS = true;
 
@@ -60,7 +60,7 @@
     );
   }
 
-  public void testAutomaticCatchWrapping() throws Exception {
+  public void testAutomaticCatchWrapping() {
     getSettings().CATCH_ON_NEW_LINE = true;
 
     doMethodTest(
@@ -75,7 +75,7 @@
     );
   }
 
-  public void testAutomaticCatchUnwrapping() throws Exception {
+  public void testAutomaticCatchUnwrapping() {
     getSettings().CATCH_ON_NEW_LINE = false;
     getSettings().KEEP_LINE_BREAKS = true;
 
@@ -92,7 +92,7 @@
     );
   }
 
-  public void testAutomaticFinallyWrapping() throws Exception {
+  public void testAutomaticFinallyWrapping() {
     getSettings().FINALLY_ON_NEW_LINE = true;
 
     doMethodTest(
@@ -107,7 +107,7 @@
     );
   }
 
-  public void testAutomaticFinallyUnwrapping() throws Exception {
+  public void testAutomaticFinallyUnwrapping() {
     getSettings().FINALLY_ON_NEW_LINE = false;
     getSettings().KEEP_LINE_BREAKS = true;
 
@@ -124,7 +124,7 @@
     );
   }
 
-  public void testAutomaticCatchFinallyUnwrapping() throws Exception {
+  public void testAutomaticCatchFinallyUnwrapping() {
     // Inspired by IDEA-47809
     getSettings().CATCH_ON_NEW_LINE = false;
     getSettings().FINALLY_ON_NEW_LINE = false;
@@ -144,8 +144,8 @@
       "}"
     );
   }
-  
-  public void testClassInitializationBlockBracesPlacement() throws Exception {
+
+  public void testClassInitializationBlockBracesPlacement() {
     // Inspired by IDEA-54191
     getSettings().getRootSettings().getIndentOptions(StdFileTypes.JAVA).INDENT_SIZE = 4;
     getSettings().KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = false;
@@ -161,7 +161,7 @@
     );
   }
 
-  public void testBlockOfMethodWithAnnotatedParameter() throws Exception {
+  public void testBlockOfMethodWithAnnotatedParameter() {
     // Inspired by IDEA-17870
     doClassTest("public Test(@Qualifier(\"blah\") AType blah){}", "public Test(@Qualifier(\"blah\") AType blah) {\n" + "}");
   }
@@ -193,7 +193,7 @@
     );
   }
 
-  public void testSimpleAnnotatedMethodAndBraceOnNextLineStyle() throws Exception {
+  public void testSimpleAnnotatedMethodAndBraceOnNextLineStyle() {
     // Inspired by IDEA-53542
     getSettings().METHOD_BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE;
     getSettings().KEEP_SIMPLE_METHODS_IN_ONE_LINE = true;
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.java
index e21c180..4554f93 100644
--- a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ShortenClassReferencesTest.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.
@@ -61,6 +61,7 @@
   public void testSCR37254() { doTest(); }
 
   public void testTypeAnnotatedRef() {
+    myFixture.configureByFile("pkg/TA.java");
     doTest();
     for (PsiParameter parameter : PsiTreeUtil.findChildrenOfType(myFixture.getFile(), PsiParameter.class)) {
       PsiTypeElement typeElement = parameter.getTypeElement();
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java
index 5190541..4f6c448 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -34,407 +34,369 @@
  * @author dsl
  */
 public class ChangeSignatureTest extends LightRefactoringTestCase {
-  public void testSimple() throws Exception {
+  private PsiElementFactory myFactory;
+
+  public void setUp() throws Exception {
+    super.setUp();
+    myFactory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
+  }
+
+  public void testSimple() {
     doTest(null, null, null, new ParameterInfoImpl[0], new ThrownExceptionInfo[0], false);
   }
 
-  public void testParameterReorder() throws Exception {
+  public void testParameterReorder() {
     doTest(null, new ParameterInfoImpl[]{new ParameterInfoImpl(1), new ParameterInfoImpl(0)}, false);
   }
 
-  public void testWarnAboutContract() throws Exception {
+  public void testWarnAboutContract() {
     try {
       doTest(null, new ParameterInfoImpl[]{new ParameterInfoImpl(1), new ParameterInfoImpl(0)}, false);
       fail("Conflict expected");
     }
-    catch (BaseRefactoringProcessor.ConflictsInTestsException ignored) {
-    }
+    catch (BaseRefactoringProcessor.ConflictsInTestsException ignored) { }
   }
 
-  public void testGenericTypes() throws Exception {
+  public void testGenericTypes() {
     doTest(null, null, "T", new GenParams() {
       @Override
       public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
-        final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
         return new ParameterInfoImpl[]{
-          new ParameterInfoImpl(-1, "x", factory.createTypeFromText("T", method.getParameterList()), "null"),
-          new ParameterInfoImpl(-1, "y", factory.createTypeFromText("C<T>", method.getParameterList()), "null")
+          new ParameterInfoImpl(-1, "x", myFactory.createTypeFromText("T", method.getParameterList()), "null"),
+          new ParameterInfoImpl(-1, "y", myFactory.createTypeFromText("C<T>", method.getParameterList()), "null")
         };
       }
     }, false);
   }
 
-  public void testGenericTypesInOldParameters() throws Exception {
+  public void testGenericTypesInOldParameters() {
     doTest(null, null, null, new GenParams() {
       @Override
       public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
-        final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
-        return new ParameterInfoImpl[] {
-          new ParameterInfoImpl(0, "t", factory.createTypeFromText("T", method), null)
+        return new ParameterInfoImpl[]{
+          new ParameterInfoImpl(0, "t", myFactory.createTypeFromText("T", method), null)
         };
       }
     }, false);
   }
 
-  public void testTypeParametersInMethod() throws Exception {
+  public void testTypeParametersInMethod() {
     doTest(null, null, null, new GenParams() {
-             @Override
-             public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
-               final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
-               return new ParameterInfoImpl[]{
-                   new ParameterInfoImpl(-1, "t", factory.createTypeFromText("T", method.getParameterList()), "null"),
-                   new ParameterInfoImpl(-1, "u", factory.createTypeFromText("U", method.getParameterList()), "null"),
-                   new ParameterInfoImpl(-1, "cu", factory.createTypeFromText("C<U>", method.getParameterList()), "null")
-                 };
-             }
-           }, false);
+      @Override
+      public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
+        return new ParameterInfoImpl[]{
+          new ParameterInfoImpl(-1, "t", myFactory.createTypeFromText("T", method.getParameterList()), "null"),
+          new ParameterInfoImpl(-1, "u", myFactory.createTypeFromText("U", method.getParameterList()), "null"),
+          new ParameterInfoImpl(-1, "cu", myFactory.createTypeFromText("C<U>", method.getParameterList()), "null")
+        };
+      }
+    }, false);
   }
 
-  public void testDefaultConstructor() throws Exception {
+  public void testDefaultConstructor() {
     doTest(null,
-           new ParameterInfoImpl[] {
-              new ParameterInfoImpl(-1, "j", PsiType.INT, "27")
-           }, false);
+           new ParameterInfoImpl[]{
+             new ParameterInfoImpl(-1, "j", PsiType.INT, "27")
+           }, false
+    );
   }
 
-  public void testGenerateDelegate() throws Exception {
+  public void testGenerateDelegate() {
     doTest(null,
-           new ParameterInfoImpl[] {
+           new ParameterInfoImpl[]{
              new ParameterInfoImpl(-1, "i", PsiType.INT, "27")
-           }, true);
+           }, true
+    );
   }
 
-  public void testGenerateDelegateForAbstract() throws Exception {
+  public void testGenerateDelegateForAbstract() {
     doTest(null,
-           new ParameterInfoImpl[] {
+           new ParameterInfoImpl[]{
              new ParameterInfoImpl(-1, "i", PsiType.INT, "27")
-           }, true);
+           }, true
+    );
   }
 
-  public void testGenerateDelegateWithReturn() throws Exception {
+  public void testGenerateDelegateWithReturn() {
     doTest(null,
-           new ParameterInfoImpl[] {
+           new ParameterInfoImpl[]{
              new ParameterInfoImpl(-1, "i", PsiType.INT, "27")
-           }, true);
+           }, true
+    );
   }
 
-  public void testGenerateDelegateWithParametersReordering() throws Exception {
+  public void testGenerateDelegateWithParametersReordering() {
     doTest(null,
-           new ParameterInfoImpl[] {
+           new ParameterInfoImpl[]{
              new ParameterInfoImpl(1),
              new ParameterInfoImpl(-1, "c", PsiType.CHAR, "'a'"),
              new ParameterInfoImpl(0, "j", PsiType.INT)
-           }, true);
+           }, true
+    );
   }
 
-  public void testGenerateDelegateConstructor() throws Exception {
+  public void testGenerateDelegateConstructor() {
     doTest(null, new ParameterInfoImpl[0], true);
   }
 
-  public void testGenerateDelegateDefaultConstructor() throws Exception {
-    doTest(null, new ParameterInfoImpl[] {
+  public void testGenerateDelegateDefaultConstructor() {
+    doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(-1, "i", PsiType.INT, "27")
     }, true);
   }
 
-  public void testSCR40895() throws Exception {
-    doTest(null, new ParameterInfoImpl[] {
+  public void testSCR40895() {
+    doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(0, "y", PsiType.INT),
       new ParameterInfoImpl(1, "b", PsiType.BOOLEAN)
     }, false);
   }
 
-  public void testJavadocGenericsLink() throws Exception {
-    doTest(null, new ParameterInfoImpl[] {
-      new ParameterInfoImpl(-1, "y", JavaPsiFacade.getElementFactory(getProject()).createTypeFromText("java.util.List<java.lang.String>", null)),
+  public void testJavadocGenericsLink() {
+    doTest(null, new ParameterInfoImpl[]{
+      new ParameterInfoImpl(-1, "y", myFactory.createTypeFromText("java.util.List<java.lang.String>", null)),
       new ParameterInfoImpl(0, "a", PsiType.BOOLEAN)
     }, false);
   }
 
-  public void testParamNameSameAsFieldName() throws Exception {
-    doTest(null, new ParameterInfoImpl[] {
+  public void testParamNameSameAsFieldName() {
+    doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(0, "fieldName", PsiType.INT)
     }, false);
   }
 
-  public void testParamNameNoConflict() throws Exception {
+  public void testParamNameNoConflict() {
     doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(0),
       new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN)
     }, false);
   }
 
-  public void testParamJavadoc() throws Exception {
-    doTest(null, new ParameterInfoImpl[] {
+  public void testParamJavadoc() {
+    doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(1, "z", PsiType.INT),
       new ParameterInfoImpl(0, "y", PsiType.INT)
     }, false);
   }
 
-  public void testParamJavadoc0() throws Exception {
-    doTest(null, new ParameterInfoImpl[] {
+  public void testParamJavadoc0() {
+    doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(1, "z", PsiType.INT),
       new ParameterInfoImpl(0, "y", PsiType.INT)
     }, false);
   }
 
-  public void testParamJavadoc1() throws Exception {
+  public void testParamJavadoc1() {
     doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(0, "z", PsiType.BOOLEAN)
     }, false);
   }
 
-  public void testParamJavadoc2() throws Exception {
+  public void testParamJavadoc2() {
     doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(-1, "z", PsiType.BOOLEAN),
       new ParameterInfoImpl(0, "a", PsiType.BOOLEAN),
     }, false);
   }
 
-  public void testJavadocNoNewLineInserted() throws Exception {
+  public void testJavadocNoNewLineInserted() {
     doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(0, "newArgs", PsiType.DOUBLE),
     }, false);
   }
 
-  public void testSuperCallFromOtherMethod() throws Exception {
-    doTest(null, new ParameterInfoImpl[] {
+  public void testSuperCallFromOtherMethod() {
+    doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(-1, "nnn", PsiType.INT, "-222"),
     }, false);
   }
 
-  public void testUseAnyVariable() throws Exception {
+  public void testUseAnyVariable() {
     doTest(null, null, null, new GenParams() {
       @Override
       public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
-        final PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
-        return new ParameterInfoImpl[] {
-          new ParameterInfoImpl(-1, "l", factory.createTypeFromText("List", method), "null", true)
+        return new ParameterInfoImpl[]{
+          new ParameterInfoImpl(-1, "l", myFactory.createTypeFromText("List", method), "null", true)
         };
       }
     }, false);
   }
 
-  public void testUseThisAsAnyVariable() throws Exception {
+  public void testUseThisAsAnyVariable() {
     doTest(null, null, null, new GenParams() {
       @Override
       public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
-        final PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
-        return new ParameterInfoImpl[] {
-          new ParameterInfoImpl(-1, "l", factory.createTypeFromText("List", method), "null", true)
+        return new ParameterInfoImpl[]{
+          new ParameterInfoImpl(-1, "l", myFactory.createTypeFromText("List", method), "null", true)
         };
       }
     }, false);
   }
 
-  public void testUseAnyVariableAndDefault() throws Exception {
+  public void testUseAnyVariableAndDefault() {
     doTest(null, null, null, new GenParams() {
       @Override
       public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
-        final PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
-        return new ParameterInfoImpl[] {
-          new ParameterInfoImpl(-1, "c", factory.createTypeFromText("C", method), "null", true)
+        return new ParameterInfoImpl[]{
+          new ParameterInfoImpl(-1, "c", myFactory.createTypeFromText("C", method), "null", true)
         };
       }
     }, false);
   }
 
-  public void testRemoveVarargParameter() throws Exception {
+  public void testRemoveVarargParameter() {
     doTest(null, null, null, new ParameterInfoImpl[]{new ParameterInfoImpl(0)}, new ThrownExceptionInfo[0], false);
   }
 
-  public void testEnumConstructor() throws Exception {
-    doTest(null, new ParameterInfoImpl[] {
+  public void testEnumConstructor() {
+    doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(-1, "i", PsiType.INT, "10")
     }, false);
   }
 
-  public void testVarargs1() throws Exception {
-    doTest(null, new ParameterInfoImpl[] {
+  public void testVarargs1() {
+    doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN, "true"),
       new ParameterInfoImpl(0)
     }, false);
   }
 
-  public void testVarargs2() throws Exception {
-    doTest(null, new ParameterInfoImpl[] {
+  public void testVarargs2() {
+    doTest(null, new ParameterInfoImpl[]{
       new ParameterInfoImpl(1, "i", PsiType.INT),
       new ParameterInfoImpl(0, "b", new PsiEllipsisType(PsiType.BOOLEAN))
     }, false);
   }
 
-  public void testCovariantReturnType() throws Exception {
+  public void testCovariantReturnType() {
     doTest(CommonClassNames.JAVA_LANG_RUNNABLE, new ParameterInfoImpl[0], false);
   }
 
-  public void testReorderExceptions() throws Exception {
+  public void testReorderExceptions() {
     doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]),
-           new SimpleExceptionsGen(new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(1), new JavaThrownExceptionInfo(0)}),
-           false);
+           new SimpleExceptionsGen(new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(1), new JavaThrownExceptionInfo(0)}), false);
   }
 
-  public void testAlreadyHandled() throws Exception {
+  public void testAlreadyHandled() {
     doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]),
            new GenExceptions() {
              @Override
              public ThrownExceptionInfo[] genExceptions(PsiMethod method) {
-               return new ThrownExceptionInfo[] {
-                 new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope()))
+               return new ThrownExceptionInfo[]{
+                 new JavaThrownExceptionInfo(-1, myFactory.createTypeByFQClassName("java.lang.Exception", method.getResolveScope()))
                };
              }
            },
-           false);
+           false
+    );
   }
 
-  public void testConstructorException() throws Exception {
+  public void testConstructorException() {
     doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]),
            new GenExceptions() {
              @Override
              public ThrownExceptionInfo[] genExceptions(PsiMethod method) {
-               return new ThrownExceptionInfo[] {
-                 new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.io.IOException", method.getResolveScope()))
+               return new ThrownExceptionInfo[]{
+                 new JavaThrownExceptionInfo(-1, myFactory.createTypeByFQClassName("java.io.IOException", method.getResolveScope()))
                };
              }
            },
-           false);
+           false
+    );
   }
 
-  public void testAddRuntimeException() throws Exception {
+  public void testAddRuntimeException() {
     doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]),
            new GenExceptions() {
              @Override
              public ThrownExceptionInfo[] genExceptions(PsiMethod method) {
-               return new ThrownExceptionInfo[] {
-                 new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.RuntimeException", method.getResolveScope()))
+               return new ThrownExceptionInfo[]{
+                 new JavaThrownExceptionInfo(-1, myFactory.createTypeByFQClassName("java.lang.RuntimeException", method.getResolveScope()))
                };
              }
            },
-           false);
+           false
+    );
   }
 
-  public void testAddException() throws Exception {
+  public void testAddException() {
     doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]),
            new GenExceptions() {
              @Override
              public ThrownExceptionInfo[] genExceptions(PsiMethod method) {
-               return new ThrownExceptionInfo[] {
-                 new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope()))
+               return new ThrownExceptionInfo[]{
+                 new JavaThrownExceptionInfo(-1, myFactory.createTypeByFQClassName("java.lang.Exception", method.getResolveScope()))
                };
              }
            },
-           false);
+           false
+    );
   }
 
-  public void testReorderWithVarargs() throws Exception {  // IDEADEV-26977
-    final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
-    doTest(null, new ParameterInfoImpl[] {
-        new ParameterInfoImpl(1),
-        new ParameterInfoImpl(0, "s", factory.createTypeFromText("java.lang.String...", getFile()))
+  public void testReorderWithVarargs() {  // IDEADEV-26977
+    doTest(null, new ParameterInfoImpl[]{
+      new ParameterInfoImpl(1),
+      new ParameterInfoImpl(0, "s", myFactory.createTypeFromText("java.lang.String...", getFile()))
     }, false);
   }
 
-  public void testIntroduceParameterWithDefaultValueInHierarchy() throws Exception {
+  public void testIntroduceParameterWithDefaultValueInHierarchy() {
     doTest(null, new ParameterInfoImpl[]{new ParameterInfoImpl(-1, "i", PsiType.INT, "0")}, false);
   }
 
-  public void testReorderMultilineMethodParameters() throws Exception {
+  public void testReorderMultilineMethodParameters() {
     // Inspired by IDEA-54902
-    doTest(null, new ParameterInfoImpl[] {new ParameterInfoImpl(1), new ParameterInfoImpl(0)}, false);
+    doTest(null, new ParameterInfoImpl[]{new ParameterInfoImpl(1), new ParameterInfoImpl(0)}, false);
   }
 
-  public void testRemoveFirstParameter() throws Exception {
+  public void testRemoveFirstParameter() {
     doTest(null, new ParameterInfoImpl[]{new ParameterInfoImpl(1)}, false);
   }
 
-  public void testReplaceVarargWithArray() throws Exception {
+  public void testReplaceVarargWithArray() {
     doTest(null, null, null, new GenParams() {
       @Override
       public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
-        final PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
-        return new ParameterInfoImpl[] {
-          new ParameterInfoImpl(1, "l", factory.createTypeFromText("List<T>[]", method.getParameterList()), "null", false),
-          new ParameterInfoImpl(0, "s", factory.createTypeFromText("String", method.getParameterList()))
+        return new ParameterInfoImpl[]{
+          new ParameterInfoImpl(1, "l", myFactory.createTypeFromText("List<T>[]", method.getParameterList()), "null", false),
+          new ParameterInfoImpl(0, "s", myFactory.createTypeFromText("String", method.getParameterList()))
         };
       }
     }, false);
   }
 
-  public void testMethodParametersAlignmentAfterMethodNameChange() throws Exception {
+  public void testMethodParametersAlignmentAfterMethodNameChange() {
     getCurrentCodeStyleSettings().ALIGN_MULTILINE_PARAMETERS = true;
     getCurrentCodeStyleSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
     doTest(null, "test123asd", null, new SimpleParameterGen(), new SimpleExceptionsGen(), false);
   }
 
-  public void testMethodParametersAlignmentAfterMethodVisibilityChange() throws Exception {
+  public void testMethodParametersAlignmentAfterMethodVisibilityChange() {
     getCurrentCodeStyleSettings().ALIGN_MULTILINE_PARAMETERS = true;
     getCurrentCodeStyleSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
     doTest(PsiModifier.PROTECTED, null, null, new SimpleParameterGen(), new SimpleExceptionsGen(), false);
   }
 
-  public void testMethodParametersAlignmentAfterMethodReturnTypeChange() throws Exception {
+  public void testMethodParametersAlignmentAfterMethodReturnTypeChange() {
     getCurrentCodeStyleSettings().ALIGN_MULTILINE_PARAMETERS = true;
     getCurrentCodeStyleSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
     doTest(null, null, "Exception", new SimpleParameterGen(), new SimpleExceptionsGen(), false);
   }
 
-  public void testVisibilityOfOverriddenMethod() throws Exception {
+  public void testVisibilityOfOverriddenMethod() {
     doTest(PsiModifier.PACKAGE_LOCAL, "foo", "void", new ParameterInfoImpl[0], new ThrownExceptionInfo[0], false);
   }
 
-  public void testRemoveExceptions() throws Exception {
+  public void testRemoveExceptions() {
     doTest(null, null, "void", new SimpleParameterGen(), new SimpleExceptionsGen(), false);
   }
 
-  private void doTest(@Nullable String newReturnType,
-                      ParameterInfoImpl[] parameterInfos,
-                      final boolean generateDelegate) throws Exception {
-    doTest(null, null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate);
-  }
-
-  private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
-                      @Nullable String newName,
-                      @Nullable String newReturnType,
-                      ParameterInfoImpl[] parameterInfo,
-                      ThrownExceptionInfo[] exceptionInfo,
-                      final boolean generateDelegate) throws Exception {
-    doTest(newVisibility, newName, newReturnType, new SimpleParameterGen(parameterInfo), new SimpleExceptionsGen(exceptionInfo), generateDelegate);
-  }
-
-  private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
-                      @Nullable String newName,
-                      @Nullable @NonNls String newReturnType,
-                      GenParams gen, final boolean generateDelegate) throws Exception {
-    doTest(newVisibility, newName, newReturnType, gen, new SimpleExceptionsGen(), generateDelegate);
-  }
-
-  private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
-                      @Nullable String newName,
-                      @Nullable String newReturnType,
-                      GenParams genParams,
-                      GenExceptions genExceptions,
-                      final boolean generateDelegate) throws Exception {
+  public void testPropagateParameter() {
     String basePath = "/refactoring/changeSignature/" + getTestName(false);
-    @NonNls final String filePath = basePath + ".java";
-    configureByFile(filePath);
+    configureByFile(basePath + ".java");
     final PsiElement targetElement = TargetElementUtilBase.findTargetElement(getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
     assertTrue("<caret> is not on method name", targetElement instanceof PsiMethod);
-    PsiMethod method = (PsiMethod) targetElement;
-    final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
-    PsiType newType = newReturnType != null ? factory.createTypeFromText(newReturnType, method) : method.getReturnType();
-    new ChangeSignatureProcessor(getProject(), method, generateDelegate, newVisibility,
-                                 newName != null ? newName : method.getName(),
-                                 newType, genParams.genParams(method), genExceptions.genExceptions(method)).run();
-    @NonNls String after = basePath + "_after.java";
-    checkResultByFile(after);
-  }
-
-  public void testPropagateParameter() throws Exception {
-    String basePath = "/refactoring/changeSignature/" + getTestName(false);
-    @NonNls final String filePath = basePath + ".java";
-    configureByFile(filePath);
-    final PsiElement targetElement = TargetElementUtilBase.findTargetElement(getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
-    assertTrue("<caret> is not on method name", targetElement instanceof PsiMethod);
-    PsiMethod method = (PsiMethod) targetElement;
+    PsiMethod method = (PsiMethod)targetElement;
     final PsiClass containingClass = method.getContainingClass();
     assertTrue(containingClass != null);
     final PsiMethod[] callers = containingClass.findMethodsByName("caller", false);
@@ -443,14 +405,53 @@
     final HashSet<PsiMethod> propagateParametersMethods = new HashSet<PsiMethod>();
     propagateParametersMethods.add(caller);
     final PsiParameter[] parameters = method.getParameterList().getParameters();
-    new ChangeSignatureProcessor(getProject(), method, false, null,
-                                 method.getName(),
+    new ChangeSignatureProcessor(getProject(), method, false, null, method.getName(),
                                  CanonicalTypes.createTypeWrapper(PsiType.VOID), new ParameterInfoImpl[]{
-        new ParameterInfoImpl(0, parameters[0].getName(), parameters[0].getType()),
-        new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN)}, null,
-                                 propagateParametersMethods, null).run();
-    @NonNls String after = basePath + "_after.java";
-    checkResultByFile(after);
+      new ParameterInfoImpl(0, parameters[0].getName(), parameters[0].getType()),
+      new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN)}, null, propagateParametersMethods, null
+    ).run();
+    checkResultByFile(basePath + "_after.java");
+  }
+
+  /* workers */
+
+  private void doTest(@Nullable String newReturnType, ParameterInfoImpl[] parameterInfos, boolean generateDelegate) {
+    doTest(null, null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate);
+  }
+
+  private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
+                      @Nullable String newName,
+                      @Nullable String newReturnType,
+                      ParameterInfoImpl[] parameterInfo,
+                      ThrownExceptionInfo[] exceptionInfo,
+                      boolean generateDelegate) {
+    doTest(newVisibility, newName, newReturnType, new SimpleParameterGen(parameterInfo), new SimpleExceptionsGen(exceptionInfo), generateDelegate);
+  }
+
+  private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
+                      @Nullable String newName,
+                      @Nullable @NonNls String newReturnType,
+                      GenParams gen,
+                      boolean generateDelegate) {
+    doTest(newVisibility, newName, newReturnType, gen, new SimpleExceptionsGen(), generateDelegate);
+  }
+
+  private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
+                      @Nullable String newName,
+                      @Nullable String newReturnType,
+                      GenParams genParams,
+                      GenExceptions genExceptions,
+                      boolean generateDelegate) {
+    String basePath = "/refactoring/changeSignature/" + getTestName(false);
+    configureByFile(basePath + ".java");
+    PsiElement targetElement = TargetElementUtilBase.findTargetElement(getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
+    assertTrue("<caret> is not on method name", targetElement instanceof PsiMethod);
+    PsiMethod method = (PsiMethod)targetElement;
+    PsiType newType = newReturnType != null ? myFactory.createTypeFromText(newReturnType, method) : method.getReturnType();
+    new ChangeSignatureProcessor(getProject(), method, generateDelegate, newVisibility,
+                                 newName != null ? newName : method.getName(),
+                                 newType, genParams.genParams(method), genExceptions.genExceptions(method)).run();
+    checkResultByFile(basePath + "_after.java");
   }
 
   private interface GenParams {
@@ -460,8 +461,7 @@
   private static class SimpleParameterGen implements GenParams {
     private ParameterInfoImpl[] myInfos;
 
-    private SimpleParameterGen() {
-    }
+    private SimpleParameterGen() { }
 
     private SimpleParameterGen(ParameterInfoImpl[] infos) {
       myInfos = infos;
diff --git a/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java b/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java
index 2749c34..7521d3b 100644
--- a/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java
+++ b/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java
@@ -21,16 +21,22 @@
 import com.intellij.openapi.util.InvalidDataException;
 import com.intellij.openapi.util.JDOMExternalizable;
 import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import com.intellij.util.xmlb.annotations.Transient;
 import org.jdom.Element;
 
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+@Tag("class-filter")
 public class ClassFilter implements JDOMExternalizable, Cloneable{
   private static final Logger LOG = Logger.getInstance("#com.intellij.ui.classFilter.ClassFilter");
   public static final ClassFilter[] EMPTY_ARRAY = new ClassFilter[0];
 
+  @Attribute("pattern")
   public String PATTERN = "";
+  @Attribute("enabled")
   public boolean ENABLED = true;
   private Matcher myMatcher;  // to speedup matching
 
@@ -42,9 +48,12 @@
     ENABLED = true;
   }
 
+  @Transient
   public String getPattern() {
     return PATTERN;
   }
+
+  @Transient
   public boolean isEnabled() {
     return ENABLED;
   }
diff --git a/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java
index 26e0eb5..d7dfea8 100644
--- a/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java
+++ b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java
@@ -311,26 +311,26 @@
 
           String suspendPolicy = readValue(comment, "suspendPolicy");
           if (suspendPolicy != null) {
-            breakpoint.SUSPEND = !DebuggerSettings.SUSPEND_NONE.equals(suspendPolicy);
-            breakpoint.SUSPEND_POLICY = suspendPolicy;
+            //breakpoint.setSuspend(!DebuggerSettings.SUSPEND_NONE.equals(suspendPolicy));
+            breakpoint.setSuspendPolicy(suspendPolicy);
             println("SUSPEND_POLICY = " + suspendPolicy, ProcessOutputTypes.SYSTEM);
           }
           String condition = readValue(comment, "Condition");
           if (condition != null) {
-            breakpoint.CONDITION_ENABLED = true;
+            //breakpoint.CONDITION_ENABLED = true;
             breakpoint.setCondition(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, condition));
             println("Condition = " + condition, ProcessOutputTypes.SYSTEM);
           }
           String passCount = readValue(comment, "Pass count");
           if (passCount != null) {
-            breakpoint.COUNT_FILTER_ENABLED = true;
-            breakpoint.COUNT_FILTER = Integer.parseInt(passCount);
+            breakpoint.setCountFilterEnabled(true);
+            breakpoint.setCountFilter(Integer.parseInt(passCount));
             println("Pass count = " + passCount, ProcessOutputTypes.SYSTEM);
           }
 
           String classFilters = readValue(comment, "Class filters");
           if (classFilters != null) {
-            breakpoint.CLASS_FILTERS_ENABLED = true;
+            breakpoint.setClassFiltersEnabled(true);
             StringTokenizer tokenizer = new StringTokenizer(classFilters, " ,");
             ArrayList<ClassFilter> lst = new ArrayList<ClassFilter>();
 
diff --git a/java/testFramework/src/com/intellij/testFramework/ModuleTestCase.java b/java/testFramework/src/com/intellij/testFramework/ModuleTestCase.java
index f6f1400..5930288 100644
--- a/java/testFramework/src/com/intellij/testFramework/ModuleTestCase.java
+++ b/java/testFramework/src/com/intellij/testFramework/ModuleTestCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 
 public abstract class ModuleTestCase extends IdeaTestCase {
   protected final Collection<Module> myModulesToDispose = new ArrayList<Module>();
@@ -100,6 +101,7 @@
         @Override
         public Module compute() {
           try {
+            LocalFileSystem.getInstance().refreshIoFiles(Collections.singletonList(moduleFile));
             return ModuleManager.getInstance(myProject).loadModule(moduleFile.getAbsolutePath());
           }
           catch (Exception e) {
@@ -162,6 +164,7 @@
     FileUtil.copyDir(dirInTestDataFile, moduleDir);
     final Module module = createModule(moduleDir + "/" + newModuleFileName, moduleType);
     final VirtualFile root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(moduleDir);
+    assertNotNull(root);
     new WriteCommandAction.Simple(module.getProject()) {
       @Override
       protected void run() throws Throwable {
diff --git a/jps/jps-builders/jps-builders.iml b/jps/jps-builders/jps-builders.iml
index fea80a0..9dd56d5 100644
--- a/jps/jps-builders/jps-builders.iml
+++ b/jps/jps-builders/jps-builders.iml
@@ -36,6 +36,7 @@
     <orderEntry type="module" module-name="jps-model-serialization" />
     <orderEntry type="module" module-name="jps-model-impl" />
     <orderEntry type="library" scope="TEST" name="Groovy" level="project" />
+    <orderEntry type="module" module-name="jps-serialization-tests" scope="TEST" />
   </component>
 </module>
 
diff --git a/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.JavaCompilingTool b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.JavaCompilingTool
new file mode 100644
index 0000000..f26b048
--- /dev/null
+++ b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.JavaCompilingTool
@@ -0,0 +1,2 @@
+org.jetbrains.jps.builders.impl.java.JavacCompilerTool
+org.jetbrains.jps.builders.impl.java.EclipseCompilerTool
\ No newline at end of file
diff --git a/jps/jps-builders/src/org/jetbrains/jps/ModuleChunk.java b/jps/jps-builders/src/org/jetbrains/jps/ModuleChunk.java
index 683a8b0..5f74fa2 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/ModuleChunk.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/ModuleChunk.java
@@ -50,6 +50,21 @@
     myContainsTests = containsTests;
   }
 
+  public String getPresentableShortName() {
+    String name = myModules.iterator().next().getName();
+    if (myModules.size() > 1) {
+      name += " and " + (myModules.size() - 1) + " more";
+      String fullName = getName();
+      if (fullName.length() < name.length()) {
+        name = fullName;
+      }
+    }
+    if (containsTests()) {
+      name = "tests of " + name;
+    }
+    return name;
+  }
+
   public String getName() {
     if (myModules.size() == 1) return myModules.iterator().next().getName();
     return StringUtil.join(myModules, GET_NAME, ",");
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/EclipseCompilerTool.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/EclipseCompilerTool.java
new file mode 100644
index 0000000..bea32c0
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/EclipseCompilerTool.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ * 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 org.jetbrains.jps.builders.impl.java;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.java.CannotCreateJavaCompilerException;
+import org.jetbrains.jps.builders.java.JavaCompilingTool;
+import org.jetbrains.jps.cmdline.ClasspathBootstrap;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.Utils;
+import org.jetbrains.jps.model.java.compiler.JavaCompilers;
+
+import javax.tools.*;
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import java.util.ServiceLoader;
+
+/**
+ * @author nik
+ */
+public class EclipseCompilerTool extends JavaCompilingTool {
+  @NotNull
+  @Override
+  public String getId() {
+    return JavaCompilers.ECLIPSE_ID;
+  }
+
+  @Nullable
+  @Override
+  public String getAlternativeId() {
+    return JavaCompilers.ECLIPSE_EMBEDDED_ID;
+  }
+
+  @NotNull
+  @Override
+  public String getDescription() {
+    return "Eclipse compiler";
+  }
+
+  @NotNull
+  @Override
+  public JavaCompiler createCompiler() throws CannotCreateJavaCompilerException {
+    for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) {
+      if ("EclipseCompiler".equals(StringUtil.getShortName(javaCompiler.getClass()))) {
+        return javaCompiler;
+      }
+    }
+    throw new CannotCreateJavaCompilerException("Eclipse Batch Compiler was not found in classpath");
+  }
+
+  @NotNull
+  @Override
+  public List<File> getAdditionalClasspath() {
+    for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) { // Eclipse compiler
+      final File compilerResource = ClasspathBootstrap.getResourceFile(javaCompiler.getClass());
+      final String name = compilerResource.getName();
+      if (name.startsWith("ecj-") && name.endsWith(".jar")) {
+        return Collections.singletonList(compilerResource);
+      }
+    }
+    return Collections.emptyList();
+  }
+
+  @Override
+  public void processCompilerOptions(@NotNull CompileContext context, @NotNull List<String> options) {
+    for (String option : options) {
+      if (option.startsWith("-proceedOnError")) {
+        Utils.PROCEED_ON_ERROR_KEY.set(context, Boolean.TRUE);
+        break;
+      }
+    }
+  }
+
+  @Override
+  public List<String> getDefaultCompilerOptions() {
+    return Collections.singletonList("-noExit");
+  }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/JavacCompilerTool.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/JavacCompilerTool.java
new file mode 100644
index 0000000..976e750
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/java/JavacCompilerTool.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ * 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 org.jetbrains.jps.builders.impl.java;
+
+import com.intellij.util.ExceptionUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.java.CannotCreateJavaCompilerException;
+import org.jetbrains.jps.builders.java.JavaCompilingTool;
+import org.jetbrains.jps.javac.JavacMain;
+import org.jetbrains.jps.model.java.compiler.JavaCompilers;
+
+import javax.tools.*;
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JavacCompilerTool extends JavaCompilingTool {
+  @NotNull
+  @Override
+  public String getId() {
+    return JavaCompilers.JAVAC_ID;
+  }
+
+  @Nullable
+  @Override
+  public String getAlternativeId() {
+    return JavaCompilers.JAVAC_API_ID;
+  }
+
+  @NotNull
+  @Override
+  public String getDescription() {
+    return "javac " + System.getProperty("java.version");
+  }
+
+  @NotNull
+  @Override
+  public JavaCompiler createCompiler() throws CannotCreateJavaCompilerException {
+    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+    if (compiler != null) {
+      return compiler;
+    }
+
+    String message = "System Java Compiler was not found in classpath";
+    // trying to obtain additional diagnostic for the case when compiler.jar is present, but there were problems with compiler class loading:
+    try {
+      Class.forName("com.sun.tools.javac.api.JavacTool", false, JavacMain.class.getClassLoader());
+    }
+    catch (Throwable ex) {
+      message = message + ":\n" + ExceptionUtil.getThrowableText(ex);
+    }
+    throw new CannotCreateJavaCompilerException(message);
+  }
+
+  @NotNull
+  @Override
+  public List<File> getAdditionalClasspath() {
+    return Collections.emptyList();
+  }
+
+  @Override
+  public List<String> getDefaultCompilerOptions() {
+    return Collections.singletonList("-implicit:class");
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/CannotCreateJavaCompilerException.java
similarity index 61%
copy from platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
copy to jps/jps-builders/src/org/jetbrains/jps/builders/java/CannotCreateJavaCompilerException.java
index 72c585b..4901a97 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/CannotCreateJavaCompilerException.java
@@ -13,18 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk2;
-
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.util.Consumer;
+package org.jetbrains.jps.builders.java;
 
 /**
- * @author traff
+ * @author nik
  */
-public interface RemoteSdkProducer<T extends RemoteSdkCredentials> {
-  T getRemoteSdkCredentials() throws InterruptedException;
-  
-  void produceRemoteSdkCredentials(Consumer<T> remoteSdkConsumer);
-
-  Object getRemoteSdkDataKey();
+public class CannotCreateJavaCompilerException extends Exception {
+  public CannotCreateJavaCompilerException(String message) {
+    super(message);
+  }
 }
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java
index 35de668..1f0cd41 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java
@@ -21,6 +21,7 @@
 import com.intellij.openapi.util.io.FileUtil;
 import gnu.trove.THashSet;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.jetbrains.jps.ModuleChunk;
 import org.jetbrains.jps.ProjectPaths;
 import org.jetbrains.jps.builders.BuildRootIndex;
@@ -38,6 +39,7 @@
 import org.jetbrains.jps.model.library.sdk.JpsSdk;
 import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
 import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.service.JpsServiceManager;
 
 import java.io.File;
 import java.io.IOException;
@@ -79,7 +81,7 @@
       final boolean errorsDetected = Utils.errorsDetected(context);
       if (!isForcedRecompilationAllJavaModules(context)) {
         if (context.shouldDifferentiate(chunk)) {
-          context.processMessage(new ProgressMessage("Checking dependencies... [" + chunk.getName() + "]"));
+          context.processMessage(new ProgressMessage("Checking dependencies... [" + chunk.getPresentableShortName() + "]"));
           final Set<File> allCompiledFiles = getAllCompiledFilesContainer(context);
           final Set<File> allAffectedFiles = getAllAffectedFilesContainer(context);
 
@@ -144,7 +146,7 @@
             }
           }
           else {
-            final String messageText = "Marking " + chunk.getName() + " and direct dependants for recompilation";
+            final String messageText = "Marking " + chunk.getPresentableShortName() + " and direct dependants for recompilation";
             LOG.info("Non-incremental mode: " + messageText);
             context.processMessage(new ProgressMessage(messageText));
 
@@ -172,7 +174,7 @@
         return false;
       }
 
-      context.processMessage(new ProgressMessage("Updating dependency information... [" + chunk.getName() + "]"));
+      context.processMessage(new ProgressMessage("Updating dependency information... [" + chunk.getPresentableShortName() + "]"));
 
       globalMappings.integrate(delta);
 
@@ -281,6 +283,16 @@
     return sdkLibrary.getProperties();
   }
 
+  @Nullable
+  public static JavaCompilingTool findCompilingTool(@NotNull String compilerId) {
+    for (JavaCompilingTool tool : JpsServiceManager.getInstance().getExtensions(JavaCompilingTool.class)) {
+      if (compilerId.equals(tool.getId()) || compilerId.equals(tool.getAlternativeId())) {
+        return tool;
+      }
+    }
+    return null;
+  }
+
   private static class ModulesBasedFileFilter implements Mappings.DependentFilesFilter {
     private final CompileContext myContext;
     private final Set<JpsModule> myChunkModules;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaCompilingTool.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaCompilingTool.java
new file mode 100644
index 0000000..6728cf3
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaCompilingTool.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ * 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 org.jetbrains.jps.builders.java;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.incremental.CompileContext;
+
+import javax.tools.*;
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class JavaCompilingTool {
+  @NotNull
+  public abstract String getId();
+
+  @Nullable
+  public String getAlternativeId() {
+    return null;
+  }
+
+  @NotNull
+  public abstract String getDescription();
+
+  @NotNull
+  public abstract JavaCompiler createCompiler() throws CannotCreateJavaCompilerException;
+
+  @NotNull
+  public abstract List<File> getAdditionalClasspath();
+
+  public void processCompilerOptions(@NotNull CompileContext context, @NotNull List<String> options) {
+  }
+
+  public void prepareCompilationTask(@NotNull JavaCompiler.CompilationTask task, @NotNull Collection<String> options) {
+  }
+
+  public List<String> getDefaultCompilerOptions() {
+    return Collections.emptyList();
+  }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
index e104ffd..21818f5 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -380,12 +380,12 @@
   public static DataExternalizer<ClassRepr> externalizer(final DependencyContext context) {
     return new DataExternalizer<ClassRepr>() {
       @Override
-      public void save(final DataOutput out, final ClassRepr value) throws IOException {
+      public void save(@NotNull final DataOutput out, final ClassRepr value) throws IOException {
         value.save(out);
       }
 
       @Override
-      public ClassRepr read(final DataInput in) throws IOException {
+      public ClassRepr read(@NotNull final DataInput in) throws IOException {
         return new ClassRepr(context, in);
       }
     };
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/FieldRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/FieldRepr.java
index b72e5aa..9235961 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/FieldRepr.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/FieldRepr.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
 package org.jetbrains.jps.builders.java.dependencyView;
 
 import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -57,12 +58,12 @@
   public static DataExternalizer<FieldRepr> externalizer(final DependencyContext context) {
     return new DataExternalizer<FieldRepr>() {
       @Override
-      public void save(final DataOutput out, final FieldRepr value) throws IOException {
+      public void save(@NotNull final DataOutput out, final FieldRepr value) throws IOException {
         value.save(out);
       }
 
       @Override
-      public FieldRepr read(final DataInput in) throws IOException {
+      public FieldRepr read(@NotNull final DataInput in) throws IOException {
         return new FieldRepr(context, in);
       }
     };
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java
index eb94639..560c4ce 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntIntPersistentMultiMaplet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -256,7 +256,7 @@
 
   private static class IntSetExternalizer implements DataExternalizer<TIntHashSet> {
     @Override
-    public void save(final DataOutput out, final TIntHashSet value) throws IOException {
+    public void save(@NotNull final DataOutput out, final TIntHashSet value) throws IOException {
       final Ref<IOException> exRef = new Ref<IOException>(null);
       value.forEach(new TIntProcedure() {
         @Override
@@ -278,7 +278,7 @@
     }
 
     @Override
-    public TIntHashSet read(final DataInput in) throws IOException {
+    public TIntHashSet read(@NotNull final DataInput in) throws IOException {
       final TIntHashSet result = new TIntHashSet();
       final DataInputStream stream = (DataInputStream)in;
       while (stream.available() > 0) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
index d195cbc..3dd4d44 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -245,14 +245,14 @@
     }
 
     @Override
-    public void save(final DataOutput out, final Collection<V> value) throws IOException {
+    public void save(@NotNull final DataOutput out, final Collection<V> value) throws IOException {
       for (V x : value) {
         myElementExternalizer.save(out, x);
       }
     }
 
     @Override
-    public Collection<V> read(final DataInput in) throws IOException {
+    public Collection<V> read(@NotNull final DataInput in) throws IOException {
       final Collection<V> result = myCollectionFactory.create();
       final DataInputStream stream = (DataInputStream)in;
       while (stream.available() > 0) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java
index 7b55ea7..72ad755 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/MethodRepr.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
 import com.intellij.util.io.DataExternalizer;
 import com.intellij.util.io.DataInputOutputUtil;
 import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.asm4.Type;
 import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
 
@@ -159,12 +160,12 @@
   public static DataExternalizer<MethodRepr> externalizer(final DependencyContext context) {
     return new DataExternalizer<MethodRepr>() {
       @Override
-      public void save(final DataOutput out, final MethodRepr value) throws IOException {
+      public void save(@NotNull final DataOutput out, final MethodRepr value) throws IOException {
         value.save(out);
       }
 
       @Override
-      public MethodRepr read(DataInput in) throws IOException {
+      public MethodRepr read(@NotNull DataInput in) throws IOException {
         return new MethodRepr(context, in);
       }
     };
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectPersistentMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectPersistentMultiMaplet.java
index d94d092..26a9b7a 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectPersistentMultiMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ObjectObjectPersistentMultiMaplet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -245,14 +245,14 @@
     }
 
     @Override
-    public void save(final DataOutput out, final Collection<V> value) throws IOException {
+    public void save(@NotNull final DataOutput out, final Collection<V> value) throws IOException {
       for (V x : value) {
         myElementExternalizer.save(out, x);
       }
     }
 
     @Override
-    public Collection<V> read(final DataInput in) throws IOException {
+    public Collection<V> read(@NotNull final DataInput in) throws IOException {
       final Collection<V> result = myCollectionFactory.create();
       final DataInputStream stream = (DataInputStream)in;
       while (stream.available() > 0) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java
index dbdb7a9..af85d75 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/TypeRepr.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.io.DataExternalizer;
 import com.intellij.util.io.DataInputOutputUtil;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.asm4.Type;
 import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
 
@@ -280,12 +281,12 @@
   public static DataExternalizer<AbstractType> externalizer(final DependencyContext context) {
     return new DataExternalizer<AbstractType>() {
       @Override
-      public void save(final DataOutput out, final AbstractType value) throws IOException {
+      public void save(@NotNull final DataOutput out, final AbstractType value) throws IOException {
         value.save(out);
       }
 
       @Override
-      public AbstractType read(final DataInput in) throws IOException {
+      public AbstractType read(@NotNull final DataInput in) throws IOException {
         AbstractType elementType;
         int level = 0;
 
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java
index 8db8bbc..a6b6bdd 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/UsageRepr.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
 import com.intellij.util.io.DataInputOutputUtil;
 import gnu.trove.TIntHashSet;
 import gnu.trove.TIntProcedure;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.asm4.Type;
 import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
 
@@ -505,12 +506,12 @@
   public static class AnnotationUsage extends Usage {
     public static final DataExternalizer<ElemType> elementTypeExternalizer = new DataExternalizer<ElemType>() {
       @Override
-      public void save(final DataOutput out, final ElemType value) throws IOException {
+      public void save(@NotNull final DataOutput out, final ElemType value) throws IOException {
         DataInputOutputUtil.writeINT(out, value.ordinal());
       }
 
       @Override
-      public ElemType read(final DataInput in) throws IOException {
+      public ElemType read(@NotNull final DataInput in) throws IOException {
         final int ordinal = DataInputOutputUtil.readINT(in);
         for (ElemType value : ElemType.values()) {
           if (value.ordinal() == ordinal) {
@@ -699,12 +700,12 @@
   public static DataExternalizer<Usage> externalizer(final DependencyContext context) {
     return new DataExternalizer<Usage>() {
       @Override
-      public void save(final DataOutput out, final Usage value) throws IOException {
+      public void save(@NotNull final DataOutput out, final Usage value) throws IOException {
         value.save(out);
       }
 
       @Override
-      public Usage read(DataInput in) throws IOException {
+      public Usage read(@NotNull DataInput in) throws IOException {
         final byte tag = in.readByte();
         switch (tag) {
           case CLASS_USAGE:
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.java
index c754140..eed818e 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.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.
@@ -18,6 +18,7 @@
 import com.intellij.util.io.DataExternalizer;
 import gnu.trove.TObjectIntHashMap;
 import gnu.trove.TObjectIntProcedure;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -34,7 +35,7 @@
   }
 
   @Override
-  public void save(final DataOutput out, final TObjectIntHashMap<K> map) throws IOException {
+  public void save(@NotNull final DataOutput out, final TObjectIntHashMap<K> map) throws IOException {
     out.writeInt(map.size());
     try {
       map.forEachEntry(new TObjectIntProcedure<K>() {
@@ -57,7 +58,7 @@
   }
 
   @Override
-  public TObjectIntHashMap<K> read(final DataInput in) throws IOException {
+  public TObjectIntHashMap<K> read(@NotNull final DataInput in) throws IOException {
     final int size = in.readInt();
     final TObjectIntHashMap<K> map = new TObjectIntHashMap<K>(size);
     for (int i = 0; i < size; i++) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/storage/ClassFilesIndexStorageBase.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/storage/ClassFilesIndexStorageBase.java
index 4d2b604..1eba7b5 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/storage/ClassFilesIndexStorageBase.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/storage/ClassFilesIndexStorageBase.java
@@ -163,7 +163,7 @@
   private static <V> DataExternalizer<CompiledDataValueContainer<V>> createValueContainerExternalizer(final DataExternalizer<V> valueExternalizer) {
     return new DataExternalizer<CompiledDataValueContainer<V>>() {
       @Override
-      public void save(final DataOutput out, final CompiledDataValueContainer<V> value) throws IOException {
+      public void save(@NotNull final DataOutput out, final CompiledDataValueContainer<V> value) throws IOException {
         final TIntObjectHashMap<V> underlying = value.myUnderlying;
         out.writeInt(underlying.size());
         final IOException[] ioException = {null};
@@ -187,7 +187,7 @@
       }
 
       @Override
-      public CompiledDataValueContainer<V> read(final DataInput in) throws IOException {
+      public CompiledDataValueContainer<V> read(@NotNull final DataInput in) throws IOException {
         final TIntObjectHashMap<V> map = new TIntObjectHashMap<V>();
         final int size = in.readInt();
         for (int i = 0; i < size; i++) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/EnumeratedMethodIncompleteSignature.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/EnumeratedMethodIncompleteSignature.java
index fec5e9a..b93a7da 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/EnumeratedMethodIncompleteSignature.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/EnumeratedMethodIncompleteSignature.java
@@ -53,14 +53,14 @@
   public static DataExternalizer<EnumeratedMethodIncompleteSignature> createDataExternalizer() {
     return new DataExternalizer<EnumeratedMethodIncompleteSignature>() {
       @Override
-      public void save(final DataOutput out, final EnumeratedMethodIncompleteSignature value) throws IOException {
+      public void save(@NotNull final DataOutput out, final EnumeratedMethodIncompleteSignature value) throws IOException {
         out.writeInt(value.getOwner());
         out.writeInt(value.getName());
         out.writeBoolean(value.isStatic());
       }
 
       @Override
-      public EnumeratedMethodIncompleteSignature read(final DataInput in) throws IOException {
+      public EnumeratedMethodIncompleteSignature read(@NotNull final DataInput in) throws IOException {
         return new EnumeratedMethodIncompleteSignature(in.readInt(),
                                                        in.readInt(),
                                                        in.readBoolean());
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
index d2b4c7f..c89cb50 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
@@ -32,15 +32,14 @@
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.asm4.ClassVisitor;
 import org.jetbrains.asm4.ClassWriter;
+import org.jetbrains.jps.builders.java.JavaCompilingTool;
 import org.jetbrains.jps.builders.java.JavaSourceTransformer;
 import org.jetbrains.jps.javac.JavacServer;
 import org.jetbrains.jps.model.JpsModel;
 import org.jetbrains.jps.model.impl.JpsModelImpl;
 import org.jetbrains.jps.model.serialization.JpsProjectLoader;
 
-import javax.tools.JavaCompiler;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
+import javax.tools.*;
 import java.io.File;
 import java.lang.reflect.Method;
 import java.util.*;
@@ -177,7 +176,7 @@
     }
   }
 
-  public static List<File> getJavacServerClasspath(String sdkHome, boolean useEclipseCompiler) {
+  public static List<File> getJavacServerClasspath(String sdkHome, JavaCompilingTool compilingTool) {
     final Set<File> cp = new LinkedHashSet<File>();
     cp.add(getResourceFile(JavacServer.class)); // self
     // util
@@ -236,16 +235,7 @@
       }
     }
 
-    if (useEclipseCompiler) {
-      // eclipse compiler
-      for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) { // Eclipse compiler
-        final File compilerResource = getResourceFile(javaCompiler.getClass());
-        final String name = compilerResource.getName();
-        if (name.startsWith("ecj-") && name.endsWith(".jar")) {
-          cp.add(compilerResource);
-        }
-      }
-    }
+    cp.addAll(compilingTool.getAdditionalClasspath());
 
     final Class<JavaSourceTransformer> transformerClass = JavaSourceTransformer.class;
     final ServiceLoader<JavaSourceTransformer> loader = ServiceLoader.load(transformerClass, transformerClass.getClassLoader());
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java
index 5724335..fa02244 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
 import com.intellij.util.io.DataExternalizer;
 import com.intellij.util.io.IOUtil;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.jps.incremental.storage.AbstractStateStorage;
 import org.jetbrains.jps.incremental.storage.PathStringDescriptor;
@@ -85,7 +86,7 @@
     private final byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
 
     @Override
-    public void save(DataOutput out, List<SourcePathAndRootIndex> value) throws IOException {
+    public void save(@NotNull DataOutput out, List<SourcePathAndRootIndex> value) throws IOException {
       for (SourcePathAndRootIndex pair : value) {
         IOUtil.writeUTFFast(myBuffer, out, pair.myPath);
         out.writeInt(pair.getRootIndex());
@@ -93,7 +94,7 @@
     }
 
     @Override
-    public List<SourcePathAndRootIndex> read(DataInput in) throws IOException {
+    public List<SourcePathAndRootIndex> read(@NotNull DataInput in) throws IOException {
       List<SourcePathAndRootIndex> result = new SmartList<SourcePathAndRootIndex>();
       final DataInputStream stream = (DataInputStream)in;
       while (stream.available() > 0) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
index 092b002..af1c974 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
@@ -74,7 +74,7 @@
     final String progress = getProgressMessage();
     final boolean shouldShowProgress = !StringUtil.isEmptyOrSpaces(progress);
     if (shouldShowProgress) {
-      context.processMessage(new ProgressMessage(progress + " [" + chunk.getName() + "]"));
+      context.processMessage(new ProgressMessage(progress + " [" + chunk.getPresentableShortName() + "]"));
     }
 
     ExitCode exitCode = ExitCode.NOTHING_DONE;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
index 645cdd6..db1700c 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
@@ -39,6 +39,7 @@
 import org.jetbrains.jps.builders.FileProcessor;
 import org.jetbrains.jps.builders.java.JavaBuilderExtension;
 import org.jetbrains.jps.builders.java.JavaBuilderUtil;
+import org.jetbrains.jps.builders.java.JavaCompilingTool;
 import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
 import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
 import org.jetbrains.jps.builders.java.dependencyView.Mappings;
@@ -81,7 +82,7 @@
   public static final boolean USE_EMBEDDED_JAVAC = System.getProperty(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null;
   private static final Key<Integer> JAVA_COMPILER_VERSION_KEY = Key.create("_java_compiler_version_");
   public static final Key<Boolean> IS_ENABLED = Key.create("_java_compiler_enabled_");
-  private static final Key<Boolean> IS_COMPILER_API_SUPPORTED = Key.create("_java_compiler_api_supported_");
+  private static final Key<JavaCompilingTool> COMPILING_TOOL = Key.create("_java_compiling_tool_");
   private static final Key<AtomicReference<String>> COMPILER_VERSION_INFO = Key.create("_java_compiler_version_info_");
 
   private static final Set<String> FILTERED_OPTIONS = new HashSet<String>(Arrays.<String>asList(
@@ -137,16 +138,9 @@
     if (LOG.isDebugEnabled()) {
       LOG.debug("Java compiler ID: " + compilerId);
     }
-    final boolean isJavac = JavaCompilers.JAVAC_ID.equalsIgnoreCase(compilerId) || JavaCompilers.JAVAC_API_ID.equalsIgnoreCase(compilerId);
-    final boolean isEclipse = JavaCompilers.ECLIPSE_ID.equalsIgnoreCase(compilerId) || JavaCompilers.ECLIPSE_EMBEDDED_ID.equalsIgnoreCase(compilerId);
-    IS_COMPILER_API_SUPPORTED.set(context, isJavac || isEclipse);
-    String messageText = null;
-    if (isJavac) {
-      messageText = "Using javac " + System.getProperty("java.version") + " to compile java sources";
-    }
-    else if (isEclipse) {
-      messageText = "Using eclipse compiler to compile java sources";
-    }
+    JavaCompilingTool compilingTool = JavaBuilderUtil.findCompilingTool(compilerId);
+    COMPILING_TOOL.set(context, compilingTool);
+    String messageText = compilingTool != null ? "Using " + compilingTool.getDescription() + " to compile java sources" : null;
     COMPILER_VERSION_INFO.set(context, new AtomicReference<String>(messageText));
   }
 
@@ -159,16 +153,17 @@
                         @NotNull ModuleChunk chunk,
                         @NotNull DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
                         @NotNull OutputConsumer outputConsumer) throws ProjectBuildException, IOException {
-    if (!IS_ENABLED.get(context, Boolean.TRUE) || !IS_COMPILER_API_SUPPORTED.get(context, Boolean.TRUE)) {
+    JavaCompilingTool compilingTool = COMPILING_TOOL.get(context);
+    if (!IS_ENABLED.get(context, Boolean.TRUE) || compilingTool == null) {
       return ExitCode.NOTHING_DONE;
     }
-    return doBuild(context, chunk, dirtyFilesHolder, outputConsumer);
+    return doBuild(context, chunk, dirtyFilesHolder, outputConsumer, compilingTool);
   }
 
   public ExitCode doBuild(@NotNull CompileContext context,
                           @NotNull ModuleChunk chunk,
                           @NotNull DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
-                          @NotNull OutputConsumer outputConsumer) throws ProjectBuildException, IOException {
+                          @NotNull OutputConsumer outputConsumer, JavaCompilingTool compilingTool) throws ProjectBuildException, IOException {
     try {
       final Set<File> filesToCompile = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
 
@@ -190,7 +185,7 @@
         }
       }
 
-      return compile(context, chunk, dirtyFilesHolder, filesToCompile, outputConsumer);
+      return compile(context, chunk, dirtyFilesHolder, filesToCompile, outputConsumer, compilingTool);
     }
     catch (BuildDataCorruptedException e) {
       throw e;
@@ -224,7 +219,7 @@
                            ModuleChunk chunk,
                            DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
                            Collection<File> files,
-                           OutputConsumer outputConsumer)
+                           OutputConsumer outputConsumer, @NotNull JavaCompilingTool compilingTool)
     throws Exception {
     ExitCode exitCode = ExitCode.NOTHING_DONE;
 
@@ -243,7 +238,7 @@
     // begin compilation round
     final Mappings delta = pd.dataManager.getMappings().createDelta();
     final Callbacks.Backend mappingsCallback = delta.getCallback();
-    final OutputFilesSink outputSink = new OutputFilesSink(context, outputConsumer, mappingsCallback, chunk.getName());
+    final OutputFilesSink outputSink = new OutputFilesSink(context, outputConsumer, mappingsCallback, chunk.getPresentableShortName());
     try {
       if (hasSourcesToCompile) {
         final AtomicReference<String> ref = COMPILER_VERSION_INFO.get(context);
@@ -264,7 +259,7 @@
         final DiagnosticSink diagnosticSink = new DiagnosticSink(context);
         
         final String chunkName = chunk.getName();
-        context.processMessage(new ProgressMessage("Parsing java... [" + chunkName + "]"));
+        context.processMessage(new ProgressMessage("Parsing java... [" + chunk.getPresentableShortName() + "]"));
 
         final int filesCount = files.size();
         boolean compiledOk = true;
@@ -284,7 +279,7 @@
             }
           }
           try {
-            compiledOk = compileJava(context, chunk, files, classpath, platformCp, srcPath, diagnosticSink, outputSink);
+            compiledOk = compileJava(context, chunk, files, classpath, platformCp, srcPath, diagnosticSink, outputSink, compilingTool);
           }
           finally {
             // heuristic: incorrect paths data recovery, so that the next make should not contain non-existing sources in 'recompile' list
@@ -328,7 +323,7 @@
     Collection<File> platformCp,
     Collection<File> sourcePath,
     DiagnosticOutputConsumer diagnosticSink,
-    final OutputFileConsumer outputSink) throws Exception {
+    final OutputFileConsumer outputSink, JavaCompilingTool compilingTool) throws Exception {
 
     final TasksCounter counter = new TasksCounter();
     COUNTER_KEY.set(context, counter);
@@ -372,7 +367,7 @@
     }
 
     final Map<File, Set<File>> outs = buildOutputDirectoriesMap(context, chunk);
-    final List<String> options = getCompilationOptions(context, chunk, profile);
+    final List<String> options = getCompilationOptions(context, chunk, profile, compilingTool);
     final ClassProcessingConsumer classesConsumer = new ClassProcessingConsumer(context, outputSink);
     if (LOG.isDebugEnabled()) {
       LOG.debug("Compiling chunk [" + chunk.getName() + "] with options: \"" + StringUtil.join(options, " ") + "\"");
@@ -380,13 +375,11 @@
     try {
       final boolean rc;
       if (USE_EMBEDDED_JAVAC) {
-        final boolean useEclipse = useEclipseCompiler(context);
-        rc = JavacMain.compile(
-          options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer, context.getCancelStatus(), useEclipse
-        );
+        rc = JavacMain.compile(options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer,
+                               context.getCancelStatus(), compilingTool);
       }
       else {
-        final JavacServerClient client = ensureJavacServerLaunched(context);
+        final JavacServerClient client = ensureJavacServerLaunched(context, compilingTool);
         final RequestFuture<JavacServerResponseHandler> future = client.sendCompileRequest(
           options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer
         );
@@ -404,13 +397,6 @@
     }
   }
 
-  private static boolean useEclipseCompiler(CompileContext context) {
-    JpsProject project = context.getProjectDescriptor().getProject();
-    final JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getCompilerConfiguration(project);
-    final String compilerId = configuration != null? configuration.getJavaCompilerId() : null;
-    return JavaCompilers.ECLIPSE_ID.equalsIgnoreCase(compilerId) || JavaCompilers.ECLIPSE_EMBEDDED_ID.equalsIgnoreCase(compilerId);
-  }
-
   private void submitAsyncTask(final CompileContext context, final Runnable taskRunnable) {
     final TasksCounter counter = COUNTER_KEY.get(context);
 
@@ -432,7 +418,7 @@
     });
   }
 
-  private static synchronized JavacServerClient ensureJavacServerLaunched(CompileContext context) throws Exception {
+  private static synchronized JavacServerClient ensureJavacServerLaunched(@NotNull CompileContext context, @NotNull JavaCompilingTool compilingTool) throws Exception {
     final ExternalJavacDescriptor descriptor = ExternalJavacDescriptor.KEY.get(context);
     if (descriptor != null) {
       return descriptor.client;
@@ -445,7 +431,7 @@
     final String javaHome = SystemProperties.getJavaHome();
 
     final BaseOSProcessHandler processHandler = JavacServerBootstrap.launchJavacServer(
-      javaHome, heapSize, port, Utils.getSystemRoot(), getCompilationVMOptions(context), useEclipseCompiler(context)
+      javaHome, heapSize, port, Utils.getSystemRoot(), getCompilationVMOptions(context, compilingTool), compilingTool
     );
     final JavacServerClient client = new JavacServerClient();
     try {
@@ -529,19 +515,22 @@
   private static final Key<List<String>> JAVAC_VM_OPTIONS = Key.create("_javac_vm_options_");
   private static final Key<String> USER_DEFINED_BYTECODE_TARGET = Key.create("_user_defined_bytecode_target_");
 
-  private static List<String> getCompilationVMOptions(CompileContext context) {
+  private static List<String> getCompilationVMOptions(CompileContext context, JavaCompilingTool compilingTool) {
     List<String> cached = JAVAC_VM_OPTIONS.get(context);
     if (cached == null) {
-      loadCommonJavacOptions(context);
+      loadCommonJavacOptions(context, compilingTool);
       cached = JAVAC_VM_OPTIONS.get(context);
     }
     return cached;
   }
 
-  private static List<String> getCompilationOptions(CompileContext context, ModuleChunk chunk, @Nullable ProcessorConfigProfile profile) {
+  private static List<String> getCompilationOptions(CompileContext context,
+                                                    ModuleChunk chunk,
+                                                    @Nullable ProcessorConfigProfile profile,
+                                                    @NotNull JavaCompilingTool compilingTool) {
     List<String> cached = JAVAC_OPTIONS.get(context);
     if (cached == null) {
-      loadCommonJavacOptions(context);
+      loadCommonJavacOptions(context, compilingTool);
       cached = JAVAC_OPTIONS.get(context);
       assert cached != null : context;
     }
@@ -701,7 +690,7 @@
     return javaVersion;
   }
 
-  private static void loadCommonJavacOptions(CompileContext context) {
+  private static void loadCommonJavacOptions(@NotNull CompileContext context, @NotNull JavaCompilingTool compilingTool) {
     final List<String> options = new ArrayList<String>();
     final List<String> vmOptions = new ArrayList<String>();
 
@@ -755,14 +744,7 @@
       }
     }
 
-    if (useEclipseCompiler(context)) {
-      for (String option : options) {
-        if (option.startsWith("-proceedOnError")) {
-          Utils.PROCEED_ON_ERROR_KEY.set(context, Boolean.TRUE);
-          break;
-        }
-      }
-    }
+    compilingTool.processCompilerOptions(context, options);
 
     JAVAC_OPTIONS.set(context, options);
     JAVAC_VM_OPTIONS.set(context, vmOptions);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java
index 9d34bbb..2d40d9f 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/messages/CompilerMessage.java
@@ -37,19 +37,19 @@
   private final long myLine;
   private final long myColumn;
 
-  public CompilerMessage(String compilerName, @NotNull Throwable internalError) {
+  public CompilerMessage(@NotNull String compilerName, @NotNull Throwable internalError) {
     this(compilerName, Kind.ERROR, getTextFromThrowable(internalError), null, -1L, -1L, -1L, -1L, -1L);
   }
 
-  public CompilerMessage(String compilerName, Kind kind, String messageText) {
+  public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText) {
     this(compilerName, kind, messageText, null, -1L, -1L, -1L, -1L, -1L);
   }
 
-  public CompilerMessage(String compilerName, Kind kind, String messageText, String sourcePath) {
+  public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText, String sourcePath) {
     this(compilerName, kind, messageText, sourcePath, -1L, -1L, -1L, -1L, -1L);
   }
 
-  public CompilerMessage(String compilerName, Kind kind, String messageText,
+  public CompilerMessage(@NotNull String compilerName, Kind kind, String messageText,
                          @Nullable String sourcePath,
                          long problemBeginOffset,
                          long problemEndOffset,
@@ -66,6 +66,7 @@
     myColumn = locationColumn;
   }
 
+  @NotNull
   public String getCompilerName() {
     return myCompilerName;
   }
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/FileKeyDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/FileKeyDescriptor.java
index f467dd2..c1c364c 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/FileKeyDescriptor.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/FileKeyDescriptor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.util.io.IOUtil;
 import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -31,11 +32,11 @@
 public final class FileKeyDescriptor implements KeyDescriptor<File> {
   private final byte[] buffer = IOUtil.allocReadWriteUTFBuffer();
 
-  public void save(DataOutput out, File value) throws IOException {
+  public void save(@NotNull DataOutput out, File value) throws IOException {
     IOUtil.writeUTFFast(buffer, out, value.getPath());
   }
 
-  public File read(DataInput in) throws IOException {
+  public File read(@NotNull DataInput in) throws IOException {
     return new File(IOUtil.readUTFFast(buffer, in));
   }
 
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/OneToManyPathsMapping.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/OneToManyPathsMapping.java
index 2c05163..6e8eb87 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/OneToManyPathsMapping.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/OneToManyPathsMapping.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -83,13 +83,13 @@
 
   private static class PathCollectionExternalizer implements DataExternalizer<Collection<String>> {
     private final byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
-    public void save(DataOutput out, Collection<String> value) throws IOException {
+    public void save(@NotNull DataOutput out, Collection<String> value) throws IOException {
       for (String str : value) {
         IOUtil.writeUTFFast(myBuffer, out, str);
       }
     }
 
-    public Collection<String> read(DataInput in) throws IOException {
+    public Collection<String> read(@NotNull DataInput in) throws IOException {
       final Set<String> result = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
       final DataInputStream stream = (DataInputStream)in;
       while (stream.available() > 0) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java
index 9955c6a..3ebb148 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/TimestampStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -113,7 +113,7 @@
   }
 
   private static class StateExternalizer implements DataExternalizer<TimestampPerTarget[]> {
-    public void save(DataOutput out, TimestampPerTarget[] value) throws IOException {
+    public void save(@NotNull DataOutput out, TimestampPerTarget[] value) throws IOException {
       out.writeInt(value.length);
       for (TimestampPerTarget target : value) {
         out.writeInt(target.targetId);
@@ -121,7 +121,7 @@
       }
     }
 
-    public TimestampPerTarget[] read(DataInput in) throws IOException {
+    public TimestampPerTarget[] read(@NotNull DataInput in) throws IOException {
       int size = in.readInt();
       TimestampPerTarget[] targets = new TimestampPerTarget[size];
       for (int i = 0; i < size; i++) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java
index d9c5832..450dea1 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java
@@ -16,11 +16,13 @@
 package org.jetbrains.jps.javac;
 
 import com.intellij.openapi.util.SystemInfo;
-import com.intellij.util.ExceptionUtil;
 import com.intellij.util.SmartList;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.builders.impl.java.JavacCompilerTool;
+import org.jetbrains.jps.builders.java.CannotCreateJavaCompilerException;
+import org.jetbrains.jps.builders.java.JavaCompilingTool;
 import org.jetbrains.jps.builders.java.JavaSourceTransformer;
 import org.jetbrains.jps.cmdline.ClasspathBootstrap;
 import org.jetbrains.jps.incremental.LineOutputWriter;
@@ -45,8 +47,7 @@
     "-d", "-classpath", "-cp", "-bootclasspath"
   ));
   private static final Set<String> FILTERED_SINGLE_OPTIONS = new HashSet<String>(Arrays.<String>asList(
-    /*javac options*/  "-verbose", "-proc:only", "-implicit:class", "-implicit:none", "-Xprefer:newer", "-Xprefer:source",
-    /*eclipse options*/"-noExit"
+    /*javac options*/  "-verbose", "-proc:only", "-implicit:class", "-implicit:none", "-Xprefer:newer", "-Xprefer:source"
   ));
 
   public static boolean compile(Collection<String> options,
@@ -57,52 +58,29 @@
                                 Map<File, Set<File>> outputDirToRoots,
                                 final DiagnosticOutputConsumer diagnosticConsumer,
                                 final OutputFileConsumer outputSink,
-                                CanceledStatus canceledStatus, boolean useEclipseCompiler) {
-    JavaCompiler compiler = null;
-    if (useEclipseCompiler) {
-      for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) {
-        compiler = javaCompiler;
-        break;
-      }
-      if (compiler == null) {
-        diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "Eclipse Batch Compiler was not found in classpath"));
-        return false;
-      }
+                                CanceledStatus canceledStatus, @NotNull JavaCompilingTool compilingTool) {
+    JavaCompiler compiler;
+    try {
+      compiler = compilingTool.createCompiler();
     }
-
-    final boolean nowUsingJavac;
-    if (compiler == null) {
-      compiler = ToolProvider.getSystemJavaCompiler();
-      if (compiler == null) {
-        String message = "System Java Compiler was not found in classpath";
-        // trying to obtain additional diagnostic for the case when compiler.jar is present, but there were problems with compiler class loading:
-        try {
-          Class.forName("com.sun.tools.javac.api.JavacTool", false, JavacMain.class.getClassLoader());
-        }
-        catch (Throwable ex) {
-          message = message + ":\n" + ExceptionUtil.getThrowableText(ex);
-        }
-        diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, message));
-        return false;
-      }
-      nowUsingJavac = true;
-    }
-    else {
-      nowUsingJavac = false;
+    catch (CannotCreateJavaCompilerException e) {
+      diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, e.getMessage()));
+      return false;
     }
 
     for (File outputDir : outputDirToRoots.keySet()) {
       outputDir.mkdirs();
     }
-    
+
     final List<JavaSourceTransformer> transformers = getSourceTransformers();
 
-    final JavacFileManager fileManager = new JavacFileManager(new ContextImpl(compiler, diagnosticConsumer, outputSink, canceledStatus, nowUsingJavac), transformers);
+    final boolean usingJavac = compilingTool instanceof JavacCompilerTool;
+    final JavacFileManager fileManager = new JavacFileManager(new ContextImpl(compiler, diagnosticConsumer, outputSink, canceledStatus, usingJavac), transformers);
 
     fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff
     fileManager.handleOption("-extdirs", Collections.singleton("").iterator()); // this will clear cached stuff
     fileManager.handleOption("-endorseddirs", Collections.singleton("").iterator()); // this will clear cached stuff
-    final Collection<String> _options = prepareOptions(options, nowUsingJavac);
+    final Collection<String> _options = prepareOptions(options, compilingTool);
 
     try {
       fileManager.setOutputDirectories(outputDirToRoots);
@@ -115,7 +93,7 @@
     if (!classpath.isEmpty()) {
       try {
         fileManager.setLocation(StandardLocation.CLASS_PATH, classpath);
-        if (!nowUsingJavac && !isOptionSet(options, "-processorpath")) {
+        if (!usingJavac && !isOptionSet(options, "-processorpath")) {
           // for non-javac file manager ensure annotation processor path defaults to classpath
           fileManager.setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpath);
         }
@@ -148,7 +126,7 @@
     //noinspection IOResourceOpenedButNotSafelyClosed
     final LineOutputWriter out = new LineOutputWriter() {
       protected void lineAvailable(String line) {
-        if (nowUsingJavac) {
+        if (usingJavac) {
           diagnosticConsumer.outputLineAvailable(line);
         }
         else {
@@ -169,6 +147,7 @@
       final JavaCompiler.CompilationTask task = compiler.getTask(
         out, fileManager, diagnosticConsumer, _options, null, fileManager.getJavaFileObjectsFromFiles(sources)
       );
+      compilingTool.prepareCompilationTask(task, _options);
 
       //if (!IS_VM_6_VERSION) { //todo!
       //  // Do not add the processor for JDK 1.6 because of the bugs in javac
@@ -186,7 +165,7 @@
     }
     finally {
       fileManager.close();
-      if (nowUsingJavac) {
+      if (usingJavac) {
         cleanupJavacNameTable();
       }
     }
@@ -221,14 +200,9 @@
     return false;
   }
 
-  private static Collection<String> prepareOptions(final Collection<String> options, boolean usingJavac) {
+  private static Collection<String> prepareOptions(final Collection<String> options, @NotNull JavaCompilingTool compilingTool) {
     final List<String> result = new ArrayList<String>();
-    if (usingJavac) {
-      result.add("-implicit:class"); // the option supported by javac only
-    }
-    else { // is Eclipse
-      result.add("-noExit");
-    }
+    result.addAll(compilingTool.getDefaultCompilerOptions());
     boolean skip = false;
     for (String option : options) {
       if (FILTERED_OPTIONS.contains(option)) {
@@ -236,7 +210,7 @@
         continue;
       }
       if (!skip) {
-        if (!FILTERED_SINGLE_OPTIONS.contains(option)) {
+        if (!FILTERED_SINGLE_OPTIONS.contains(option) && !compilingTool.getDefaultCompilerOptions().contains(option)) {
           result.add(option);
         }
       }
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java
index b5dc9ba..65c92e2 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java
@@ -29,6 +29,9 @@
 import io.netty.util.concurrent.ImmediateEventExecutor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.builders.impl.java.JavacCompilerTool;
+import org.jetbrains.jps.builders.java.JavaBuilderUtil;
+import org.jetbrains.jps.builders.java.JavaCompilingTool;
 import org.jetbrains.jps.service.SharedThreadPool;
 
 import javax.tools.*;
@@ -44,7 +47,7 @@
   public static final int DEFAULT_SERVER_PORT = 7878;
   public static final String SERVER_SUCCESS_START_MESSAGE = "Javac server started successfully. Listening on port: ";
   public static final String SERVER_ERROR_START_MESSAGE = "Error starting Javac Server: ";
-  public static final String USE_ECLIPSE_COMPILER_PROPERTY = "use.eclipse.compiler";
+  public static final String JPS_JAVA_COMPILING_TOOL_PROPERTY = "jps.java.compiling.tool";
 
   private ChannelRegistrar myChannelRegistrar;
 
@@ -153,7 +156,8 @@
     };
 
     try {
-      final boolean rc = JavacMain.compile(options, files, classpath, platformCp, sourcePath, outs, diagnostic, outputSink, canceledStatus, System.getProperty(USE_ECLIPSE_COMPILER_PROPERTY) != null);
+      JavaCompilingTool tool = getCompilingTool();
+      final boolean rc = JavacMain.compile(options, files, classpath, platformCp, sourcePath, outs, diagnostic, outputSink, canceledStatus, tool);
       return JavacProtoUtil.toMessage(sessionId, JavacProtoUtil.createBuildCompletedResponse(rc));
     }
     catch (Throwable e) {
@@ -163,6 +167,17 @@
     }
   }
 
+  private static JavaCompilingTool getCompilingTool() {
+    String property = System.getProperty(JPS_JAVA_COMPILING_TOOL_PROPERTY);
+    if (property != null) {
+      JavaCompilingTool tool = JavaBuilderUtil.findCompilingTool(property);
+      if (tool != null) {
+        return tool;
+      }
+    }
+    return new JavacCompilerTool();
+  }
+
   private final Set<CancelHandler> myCancelHandlers = Collections.synchronizedSet(new HashSet<CancelHandler>());
 
   public void cancelBuilds() {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java
index 40b646e..bb66e9c 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java
@@ -25,6 +25,7 @@
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.concurrency.Semaphore;
+import org.jetbrains.jps.builders.java.JavaCompilingTool;
 import org.jetbrains.jps.cmdline.ClasspathBootstrap;
 import org.jetbrains.jps.service.SharedThreadPool;
 
@@ -44,7 +45,7 @@
                                                        int port,
                                                        File workingDir,
                                                        List<String> vmOptions,
-                                                       boolean useEclipseCompiler) throws Exception {
+                                                       JavaCompilingTool compilingTool) throws Exception {
     final List<String> cmdLine = new ArrayList<String>();
     appendParam(cmdLine, getVMExecutablePath(sdkHomePath));
     appendParam(cmdLine, "-XX:MaxPermSize=150m");
@@ -82,9 +83,7 @@
       appendParam(cmdLine, "-Duser.region=" + region);
     }
 
-    if (useEclipseCompiler) {
-      appendParam(cmdLine, "-D" + JavacServer.USE_ECLIPSE_COMPILER_PROPERTY);
-    }
+    appendParam(cmdLine, "-D" + JavacServer.JPS_JAVA_COMPILING_TOOL_PROPERTY + "=" + compilingTool.getId());
 
     // this will disable standard extensions to ensure javac is loaded from the right tools.jar
     appendParam(cmdLine, "-Djava.ext.dirs=");
@@ -95,7 +94,7 @@
 
     appendParam(cmdLine, "-classpath");
 
-    final List<File> cp = ClasspathBootstrap.getJavacServerClasspath(sdkHomePath, useEclipseCompiler);
+    final List<File> cp = ClasspathBootstrap.getJavacServerClasspath(sdkHomePath, compilingTool);
     final StringBuilder classpath = new StringBuilder();
     for (File file : cp) {
       if (classpath.length() > 0) {
@@ -156,17 +155,15 @@
 
       public void onTextAvailable(ProcessEvent event, Key outputType) {
         if (outputType == ProcessOutputTypes.STDERR) {
-          try {
-            final String text = event.getText();
-            if (text != null) {
-              if (text.contains(JavacServer.SERVER_SUCCESS_START_MESSAGE) || text.contains(JavacServer.SERVER_ERROR_START_MESSAGE)) {
-                processHandler.removeProcessListener(this);
-                serverStartMessage.set(text);
-              }
+          final String text = event.getText();
+          if (text != null && (text.contains(JavacServer.SERVER_SUCCESS_START_MESSAGE) || text.contains(JavacServer.SERVER_ERROR_START_MESSAGE))) {
+            try {
+              processHandler.removeProcessListener(this);
+              serverStartMessage.set(text);
             }
-          }
-          finally {
-            semaphore.up();
+            finally {
+              semaphore.up();
+            }
           }
         }
       }
diff --git a/jps/model-impl/jps-model-impl.iml b/jps/model-impl/jps-model-impl.iml
index 5e72944..447c25c 100644
--- a/jps/model-impl/jps-model-impl.iml
+++ b/jps/model-impl/jps-model-impl.iml
@@ -4,13 +4,11 @@
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="module" module-name="util" />
     <orderEntry type="module" module-name="jps-model-api" />
-    <orderEntry type="module" module-name="testFramework" scope="TEST" />
   </component>
 </module>
 
diff --git a/jps/model-impl/jps-model-tests.iml b/jps/model-impl/jps-model-tests.iml
new file mode 100644
index 0000000..f423089
--- /dev/null
+++ b/jps/model-impl/jps-model-tests.iml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/testSrc">
+      <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="jps-model-impl" />
+    <orderEntry type="module" module-name="testFramework" exported="" scope="TEST" />
+  </component>
+</module>
+
diff --git a/jps/model-serialization/jps-model-serialization.iml b/jps/model-serialization/jps-model-serialization.iml
index 988e3c5..6859151 100644
--- a/jps/model-serialization/jps-model-serialization.iml
+++ b/jps/model-serialization/jps-model-serialization.iml
@@ -4,15 +4,12 @@
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="module" module-name="util" />
     <orderEntry type="module" module-name="jps-model-api" />
     <orderEntry type="library" exported="" name="JDOM" level="project" />
-    <orderEntry type="module" module-name="jps-model-impl" exported="" scope="TEST" />
-    <orderEntry type="module" module-name="testFramework" exported="" scope="TEST" />
   </component>
 </module>
 
diff --git a/jps/model-serialization/jps-serialization-tests.iml b/jps/model-serialization/jps-serialization-tests.iml
new file mode 100644
index 0000000..953fef2
--- /dev/null
+++ b/jps/model-serialization/jps-serialization-tests.iml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/testSrc">
+      <sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="jps-model-serialization" />
+    <orderEntry type="module" module-name="jps-model-tests" exported="" scope="TEST" />
+  </component>
+</module>
+
diff --git a/lib/netty-all-5.0.0.Alpha1.jar b/lib/netty-all-5.0.0.Alpha1.jar
deleted file mode 100644
index ff0afa0..0000000
--- a/lib/netty-all-5.0.0.Alpha1.jar
+++ /dev/null
Binary files differ
diff --git a/lib/netty-all-5.0.0.Alpha2.jar b/lib/netty-all-5.0.0.Alpha2.jar
new file mode 100644
index 0000000..d4b646a
--- /dev/null
+++ b/lib/netty-all-5.0.0.Alpha2.jar
Binary files differ
diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt
index 2e7c8bf..c368b90 100644
--- a/lib/required_for_dist.txt
+++ b/lib/required_for_dist.txt
@@ -40,7 +40,7 @@
 miglayout-swing.jar
 nanoxml-2.2.3.jar
 nekohtml-1.9.14.jar
-netty-all-5.0.0.Alpha1.jar
+netty-all-5.0.0.Alpha2.jar
 oromatcher.jar
 picocontainer.jar
 protobuf-2.5.0.jar
diff --git a/lib/src/netty-all-5.0.0.Alpha1-sources.jar b/lib/src/netty-all-5.0.0.Alpha2-sources.jar
similarity index 65%
rename from lib/src/netty-all-5.0.0.Alpha1-sources.jar
rename to lib/src/netty-all-5.0.0.Alpha2-sources.jar
index 767b4fb..354781d 100644
--- a/lib/src/netty-all-5.0.0.Alpha1-sources.jar
+++ b/lib/src/netty-all-5.0.0.Alpha2-sources.jar
Binary files differ
diff --git a/native/runner/runnerw/runnerw.vcxproj b/native/runner/runnerw/runnerw.vcxproj
index c346390..be49c0d 100644
--- a/native/runner/runnerw/runnerw.vcxproj
+++ b/native/runner/runnerw/runnerw.vcxproj
@@ -23,7 +23,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v120</PlatformToolset>
+    <PlatformToolset>v120_xp</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
diff --git a/platform/bootstrap/src/com/intellij/idea/Main.java b/platform/bootstrap/src/com/intellij/idea/Main.java
index 33a95c5..7c32853 100644
--- a/platform/bootstrap/src/com/intellij/idea/Main.java
+++ b/platform/bootstrap/src/com/intellij/idea/Main.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.
@@ -124,21 +124,20 @@
     String platform = System.getProperty(PLATFORM_PREFIX_PROPERTY, "idea");
     String patchFileName = ("jetbrains.patch.jar." + platform).toLowerCase();
     String tempDir = System.getProperty("java.io.tmpdir");
-    File originalPatchFile = new File(tempDir, patchFileName);
-    File copyPatchFile = new File(tempDir, patchFileName + "_copy");
 
     // always delete previous patch copy
-    if (!FileUtilRt.delete(copyPatchFile)) {
-      throw new IOException("Cannot create temporary patch file");
+    File patchCopy = new File(tempDir, patchFileName + "_copy");
+    File log4jCopy = new File(tempDir, "log4j.jar." + platform + "_copy");
+    if (!FileUtilRt.delete(patchCopy) || !FileUtilRt.delete(log4jCopy)) {
+      throw new IOException("Cannot delete temporary files in " + tempDir);
     }
 
-    if (!originalPatchFile.exists()) {
-      return;
-    }
-
-    if (!originalPatchFile.renameTo(copyPatchFile) || !FileUtilRt.delete(originalPatchFile)) {
-      throw new IOException("Cannot create temporary patch file");
-    }
+    File patch = new File(tempDir, patchFileName);
+    if (!patch.exists()) return;
+    File log4j = new File(PathManager.getLibPath(), "log4j.jar");
+    if (!log4j.exists()) throw new IOException("Log4J missing: " + log4j);
+    copyFile(patch, patchCopy, true);
+    copyFile(log4j, log4jCopy, false);
 
     int status = 0;
     if (Restarter.isSupported()) {
@@ -153,12 +152,13 @@
                          System.getProperty("java.home") + "/bin/java",
                          "-Xmx500m",
                          "-classpath",
-                         copyPatchFile.getPath() + File.pathSeparator + PathManager.getLibPath() + "/log4j.jar",
+                         patchCopy.getPath() + File.pathSeparator + log4jCopy.getPath(),
                          "-Djava.io.tmpdir=" + tempDir,
+                         "-Didea.updater.log=" + PathManager.getLogPath(),
+                         "-Dswing.defaultlaf=" + UIManager.getSystemLookAndFeelClassName(),
                          "com.intellij.updater.Runner",
                          "install",
-                         PathManager.getHomePath(),
-                         PathManager.getLogPath());
+                         PathManager.getHomePath());
 
       status = Restarter.scheduleRestart(ArrayUtilRt.toStringArray(args));
     }
@@ -170,6 +170,20 @@
     System.exit(status);
   }
 
+  private static void copyFile(File original, File copy, boolean move) throws IOException {
+    if (move) {
+      if (!original.renameTo(copy) || !FileUtilRt.delete(original)) {
+        throw new IOException("Cannot create temporary file: " + copy);
+      }
+    }
+    else {
+      FileUtilRt.copy(original, copy);
+      if (!copy.exists()) {
+        throw new IOException("Cannot create temporary file: " + copy);
+      }
+    }
+  }
+
   public static void showMessage(String title, Throwable t) {
     StringWriter message = new StringWriter();
     message.append("Internal error. Please report to http://");
diff --git a/platform/core-api/src/com/intellij/openapi/editor/colors/CodeInsightColors.java b/platform/core-api/src/com/intellij/openapi/editor/colors/CodeInsightColors.java
index d823f67..ede0246 100644
--- a/platform/core-api/src/com/intellij/openapi/editor/colors/CodeInsightColors.java
+++ b/platform/core-api/src/com/intellij/openapi/editor/colors/CodeInsightColors.java
@@ -32,13 +32,13 @@
   TextAttributesKey DEPRECATED_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("DEPRECATED_ATTRIBUTES");
 
   TextAttributesKey LOCAL_VARIABLE_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("LOCAL_VARIABLE_ATTRIBUTES");
-  TextAttributesKey REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES");
-  TextAttributesKey REASSIGNED_PARAMETER_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("REASSIGNED_PARAMETER_ATTRIBUTES");
+  TextAttributesKey PARAMETER_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("PARAMETER_ATTRIBUTES");
+  TextAttributesKey REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES", LOCAL_VARIABLE_ATTRIBUTES);
+  TextAttributesKey REASSIGNED_PARAMETER_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("REASSIGNED_PARAMETER_ATTRIBUTES", PARAMETER_ATTRIBUTES);
   TextAttributesKey IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES");
   TextAttributesKey INSTANCE_FIELD_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("INSTANCE_FIELD_ATTRIBUTES");
   TextAttributesKey STATIC_FIELD_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("STATIC_FIELD_ATTRIBUTES");
   TextAttributesKey STATIC_FINAL_FIELD_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("STATIC_FINAL_FIELD_ATTRIBUTES", STATIC_FIELD_ATTRIBUTES);
-  TextAttributesKey PARAMETER_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("PARAMETER_ATTRIBUTES");
   TextAttributesKey CLASS_NAME_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("CLASS_NAME_ATTRIBUTES");
   TextAttributesKey ANONYMOUS_CLASS_NAME_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("ANONYMOUS_CLASS_NAME_ATTRIBUTES");
   TextAttributesKey TYPE_PARAMETER_NAME_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("TYPE_PARAMETER_NAME_ATTRIBUTES");
diff --git a/platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java b/platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java
index fa04c3c..6385e73 100644
--- a/platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java
+++ b/platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java
@@ -62,6 +62,10 @@
     return null;
   }
 
+  /**
+   * @deprecated implement own {@link com.intellij.debugger.engine.JVMDebugProvider} instead
+   */
+  @Deprecated
   public boolean isJVMDebuggingSupported() {
     return false;
   }
diff --git a/platform/core-api/src/com/intellij/openapi/module/Module.java b/platform/core-api/src/com/intellij/openapi/module/Module.java
index b421897..6120cb0 100644
--- a/platform/core-api/src/com/intellij/openapi/module/Module.java
+++ b/platform/core-api/src/com/intellij/openapi/module/Module.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -107,8 +107,10 @@
    *
    * @return scope including sources and tests, excluding libraries and dependencies.
    */
+  @NotNull
   GlobalSearchScope getModuleScope();
 
+  @NotNull
   GlobalSearchScope getModuleScope(boolean includeTests);
 
   /**
@@ -116,6 +118,7 @@
    *
    * @return scope including sources, tests, and libraries, excluding dependencies.
    */
+  @NotNull
   GlobalSearchScope getModuleWithLibrariesScope();
 
   /**
@@ -123,13 +126,20 @@
    *
    * @return scope including sources, tests, and dependencies, excluding libraries.
    */
+  @NotNull
   GlobalSearchScope getModuleWithDependenciesScope();
 
+  @NotNull
   GlobalSearchScope getModuleContentScope();
+  @NotNull
   GlobalSearchScope getModuleContentWithDependenciesScope();
 
+  @NotNull
   GlobalSearchScope getModuleWithDependenciesAndLibrariesScope(boolean includeTests);
+  @NotNull
   GlobalSearchScope getModuleWithDependentsScope();
+  @NotNull
   GlobalSearchScope getModuleTestsWithDependentsScope();
+  @NotNull
   GlobalSearchScope getModuleRuntimeScope(boolean includeTests);
 }
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java
index 8b67321..e1c23aa 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.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.
@@ -125,6 +125,7 @@
    * @return the path
    */
   @SuppressWarnings("JavadocReference")
+  @NotNull
   public abstract String getPath();
 
   /**
@@ -727,4 +728,18 @@
   public static boolean isValidName(@NotNull String name) {
     return name.indexOf('\\') < 0 && name.indexOf('/') < 0;
   }
+
+  private static final Key<String> DETECTED_LINE_SEPARATOR_KEY = Key.create("DETECTED_LINE_SEPARATOR_KEY");
+
+  /**
+   * @return Line separator for this file.
+   * It is always null for directories and binaries, and possibly null if a separator isn't yet known.
+   * @see com.intellij.util.LineSeparator
+   */
+  public String getDetectedLineSeparator() {
+    return getUserData(DETECTED_LINE_SEPARATOR_KEY);
+  }
+  public void setDetectedLineSeparator(@Nullable String separator) {
+    putUserData(DETECTED_LINE_SEPARATOR_KEY, separator);
+  }
 }
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/encoding/EncodingRegistry.java b/platform/core-api/src/com/intellij/openapi/vfs/encoding/EncodingRegistry.java
index 34907f8..5a9a904 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/encoding/EncodingRegistry.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/encoding/EncodingRegistry.java
@@ -53,6 +53,11 @@
 
   public abstract void setEncoding(@Nullable("null means project") VirtualFile virtualFileOrDir, @Nullable("null means remove mapping") Charset charset);
 
+  @Nullable("null means 'use system-default'")
+  public Charset getDefaultCharsetForPropertiesFiles(@Nullable VirtualFile virtualFile) {
+    return null;
+  }
+
   public static EncodingRegistry getInstance() {
     if (ourInstanceGetter == null) {
       return (EncodingRegistry)ApplicationManager.getApplication().getPicoContainer().getComponentInstance("com.intellij.openapi.vfs.encoding.EncodingManager");
diff --git a/platform/core-api/src/com/intellij/psi/CommonClassNames.java b/platform/core-api/src/com/intellij/psi/CommonClassNames.java
index a7b6649..32485e7 100644
--- a/platform/core-api/src/com/intellij/psi/CommonClassNames.java
+++ b/platform/core-api/src/com/intellij/psi/CommonClassNames.java
@@ -61,6 +61,7 @@
   @NonNls String JAVA_UTIL_LIST = "java.util.List";
   @NonNls String JAVA_UTIL_ARRAY_LIST = "java.util.ArrayList";
   @NonNls String JAVA_UTIL_SET = "java.util.Set";
+  @NonNls String JAVA_UTIL_HASH_SET = "java.util.HashSet";
   @NonNls String JAVA_UTIL_PROPERTIES = "java.util.Properties";
   @NonNls String JAVA_UTIL_PROPERTY_RESOURCE_BUNDLE = "java.util.PropertyResourceBundle";
   @NonNls String JAVA_UTIL_DATE = "java.util.Date";
diff --git a/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java b/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java
index a94a146..836ad0c 100644
--- a/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java
+++ b/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java
@@ -39,7 +39,7 @@
   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.search.GlobalSearchScope");
   @Nullable private final Project myProject;
 
-  protected GlobalSearchScope(Project project) {
+  protected GlobalSearchScope(@Nullable Project project) {
     myProject = project;
   }
 
@@ -49,6 +49,7 @@
 
   public abstract boolean contains(@NotNull VirtualFile file);
 
+  @Nullable
   @Override
   public Project getProject() {
     return myProject;
diff --git a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java
index d33ee46..bb6273b 100644
--- a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java
+++ b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java
@@ -520,17 +520,27 @@
   @Nullable
   @Contract("null, _, _ -> null")
   public static <T extends PsiElement> T getParentOfType(@Nullable PsiElement element, @NotNull Class<T> aClass, boolean strict) {
-    if (element == null) return null;
+    return getParentOfType(element, aClass, strict, -1);
+  }
+
+  @Contract("null, _, _, _ -> null")
+  public static <T extends PsiElement> T getParentOfType(@Nullable PsiElement element, @NotNull Class<T> aClass, boolean strict, int minStartOffset) {
+    if (element == null) {
+      return null;
+    }
+
     if (strict) {
       element = element.getParent();
     }
 
-    while (element != null) {
+    while (element != null && (minStartOffset == -1 || element.getNode().getStartOffset() >= minStartOffset)) {
       if (aClass.isInstance(element)) {
         //noinspection unchecked
         return (T)element;
       }
-      if (element instanceof PsiFile) return null;
+      if (element instanceof PsiFile) {
+        return null;
+      }
       element = element.getParent();
     }
 
diff --git a/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java b/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java
index 158144a..55222cf 100644
--- a/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java
+++ b/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -184,6 +184,7 @@
     return myFileType;
   }
 
+  @NotNull
   @Override
   public String getPath() {
     return "/" + getName();
diff --git a/platform/core-api/src/com/intellij/util/PlatformUtilsCore.java b/platform/core-api/src/com/intellij/util/PlatformUtilsCore.java
index 19854cc..5172e15 100644
--- a/platform/core-api/src/com/intellij/util/PlatformUtilsCore.java
+++ b/platform/core-api/src/com/intellij/util/PlatformUtilsCore.java
@@ -24,7 +24,7 @@
   public static final String APPCODE_PREFIX = "AppCode";
   public static final String CPP_PREFIX = "CppIde";
   public static final String PYCHARM_PREFIX = "Python";
-  public static final String PYCHARM_PREFIX2 = "PyCharm";
+  public static final String PYCHARM_PREFIX2 = "PyCharmCore";
   public static final String RUBY_PREFIX = "Ruby";
   public static final String PHP_PREFIX = "PhpStorm";
   public static final String WEB_PREFIX = "WebStorm";
diff --git a/platform/core-impl/src/com/intellij/openapi/editor/ex/util/SegmentArray.java b/platform/core-impl/src/com/intellij/openapi/editor/ex/util/SegmentArray.java
index b3e91d6..2918656 100644
--- a/platform/core-impl/src/com/intellij/openapi/editor/ex/util/SegmentArray.java
+++ b/platform/core-impl/src/com/intellij/openapi/editor/ex/util/SegmentArray.java
@@ -27,8 +27,8 @@
  */
 public class SegmentArray {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.ex.util.SegmentArray");
-  private int[] myStarts;
-  private int[] myEnds;
+  protected int[] myStarts;
+  protected int[] myEnds;
 
   protected int mySegmentCount = 0;
   protected static final int INITIAL_SIZE = 64;
@@ -84,26 +84,32 @@
     return newArray;
   }
 
+  protected int noSegmentsAvailable(int offset) {
+    throw new IllegalStateException("no segments available. offset = " + offset);
+  }
+
+  protected int offsetOutOfRange(int offset, int lastValidOffset) {
+    throw new IndexOutOfBoundsException("Wrong offset: " + offset + ". Should be in range: [0, " + lastValidOffset + "]");
+  }
+
   public final int findSegmentIndex(int offset) {
     if (mySegmentCount <= 0) {
-      if (offset == 0) return 0;
-      throw new IllegalStateException("no segments available. offset = "+offset);
+      return offset == 0 ? 0 : noSegmentsAvailable(offset);
     }
 
     final int lastValidOffset = getLastValidOffset();
-
     if (offset > lastValidOffset || offset < 0) {
-      throw new IndexOutOfBoundsException("Wrong offset: " + offset + ". Should be in range: [0, " + lastValidOffset + "]");
+      return offsetOutOfRange(offset, lastValidOffset);
     }
 
-    final int lastValidIndex = mySegmentCount - 1;
-    if (offset == lastValidOffset) return lastValidIndex;
+    int end = mySegmentCount - 1;
+    if (offset == lastValidOffset) {
+      return end;
+    }
 
     int start = 0;
-    int end = lastValidIndex;
-
-    while (start < end) {
-      int i = (start + end) / 2;
+    while (start <= end) {
+      int i = (start + end) >>> 1;
       if (offset < myStarts[i]) {
         end = i - 1;
       }
@@ -115,9 +121,12 @@
       }
     }
 
+    return segmentNotFound(offset, start);
+  }
+
+  protected int segmentNotFound(int offset, int start) {
     // This means that there is a gap at given offset
     assert myStarts[start] <= offset && offset < myEnds[start] : start;
-
     return start;
   }
 
diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
index 3d51b6b..6be740b 100644
--- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
@@ -59,7 +59,8 @@
   private final List<RangeMarker> myGuardedBlocks = new ArrayList<RangeMarker>();
   private ReadonlyFragmentModificationHandler myReadonlyFragmentModificationHandler;
 
-  private final LineSet myLineSet = new LineSet();
+  private final Object myLineSetLock = new String("line set lock");
+  private volatile LineSet myLineSet;
   private volatile ImmutableText myText;
   private volatile SoftReference<String> myTextString;
 
@@ -110,9 +111,13 @@
   }
 
   public DocumentImpl(@NotNull CharSequence chars, boolean forUseInNonAWTThread) {
+    this(chars, false, forUseInNonAWTThread);
+  }
+
+  public DocumentImpl(@NotNull CharSequence chars, boolean acceptSlashR, boolean forUseInNonAWTThread) {
+    setAcceptSlashR(acceptSlashR);
     assertValidSeparators(chars);
     myText = ImmutableText.valueOf(chars);
-    myLineSet.documentCreated(this);
     setCyclicBufferSize(0);
     setModificationStamp(LocalTimeCounter.currentTime());
     myAssertThreading = !forUseInNonAWTThread;
@@ -127,6 +132,22 @@
     }
   }
 
+  private LineSet getLineSet() {
+    LineSet lineSet = myLineSet;
+    if (lineSet == null) {
+      synchronized (myLineSetLock) {
+        lineSet = myLineSet;
+        if (lineSet == null) {
+          lineSet = new LineSet();
+          lineSet.documentCreated(this);
+          myLineSet = lineSet;
+        }
+      }
+    }
+
+    return lineSet;
+  }
+
   @Override
   @NotNull
   public char[] getChars() {
@@ -159,11 +180,12 @@
     CharSequence text = myText;
     RangeMarker caretMarker = caretOffset < 0 || caretOffset > getTextLength() ? null : createRangeMarker(caretOffset, caretOffset);
     try {
-      for (int line = 0; line < myLineSet.getLineCount(); line++) {
-        if (inChangedLinesOnly && !myLineSet.isModified(line)) continue;
+      LineSet lineSet = getLineSet();
+      for (int line = 0; line < lineSet.getLineCount(); line++) {
+        if (inChangedLinesOnly && !lineSet.isModified(line)) continue;
         int whiteSpaceStart = -1;
-        final int lineEnd = myLineSet.getLineEnd(line) - myLineSet.getSeparatorLength(line);
-        int lineStart = myLineSet.getLineStart(line);
+        final int lineEnd = lineSet.getLineEnd(line) - lineSet.getSeparatorLength(line);
+        int lineStart = lineSet.getLineStart(line);
         for (int offset = lineEnd - 1; offset >= lineStart; offset--) {
           char c = text.charAt(offset);
           if (c != ' ' && c != '\t') {
@@ -228,12 +250,13 @@
           markers.add(marker);
         }
       }
+      LineSet lineSet = getLineSet();
       lineLoop:
-      for (int line = 0; line < myLineSet.getLineCount(); line++) {
-        if (inChangedLinesOnly && !myLineSet.isModified(line)) continue;
+      for (int line = 0; line < lineSet.getLineCount(); line++) {
+        if (inChangedLinesOnly && !lineSet.isModified(line)) continue;
         int whiteSpaceStart = -1;
-        final int lineEnd = myLineSet.getLineEnd(line) - myLineSet.getSeparatorLength(line);
-        int lineStart = myLineSet.getLineStart(line);
+        final int lineEnd = lineSet.getLineEnd(line) - lineSet.getSeparatorLength(line);
+        int lineStart = lineSet.getLineStart(line);
         for (int offset = lineEnd - 1; offset >= lineStart; offset--) {
           char c = text.charAt(offset);
           if (c != ' ' && c != '\t') {
@@ -644,19 +667,20 @@
 
   @Override
   public void clearLineModificationFlags() {
-    myLineSet.clearModificationFlags();
+    getLineSet().clearModificationFlags();
   }
 
   public void clearLineModificationFlagsExcept(@NotNull List<Integer> caretLines) {
     List<Integer> modifiedLines = new ArrayList<Integer>(caretLines.size());
+    LineSet lineSet = getLineSet();
     for (Integer line : caretLines) {
-      if (line != null && line >= 0 && line < myLineSet.getLineCount() && myLineSet.isModified(line)) {
+      if (line != null && line >= 0 && line < lineSet.getLineCount() && lineSet.isModified(line)) {
         modifiedLines.add(line);
       }
     }
     clearLineModificationFlags();
     for (Integer line : modifiedLines) {
-      myLineSet.setModified(line);
+      lineSet.setModified(line);
     }
   }
 
@@ -694,6 +718,8 @@
     }
     assertInsideCommand();
 
+    getLineSet(); // initialize line set to track changed lines
+
     DocumentEvent event = new DocumentEventImpl(this, offset, oldString, newString, myModificationStamp, wholeTextReplaced);
 
     if (!ShutDownTracker.isShutdownHookRunning()) {
@@ -725,7 +751,7 @@
     try {
       if (LOG.isDebugEnabled()) LOG.debug(event.toString());
 
-      myLineSet.changedUpdate(event);
+      getLineSet().changedUpdate(event);
       setModificationStamp(newModificationStamp);
 
       if (!ShutDownTracker.isShutdownHookRunning()) {
@@ -847,39 +873,39 @@
 
   @Override
   public int getLineNumber(final int offset) {
-    return myLineSet.findLineIndex(offset);
+    return getLineSet().findLineIndex(offset);
   }
 
   @Override
   @NotNull
   public LineIterator createLineIterator() {
-    return myLineSet.createIterator();
+    return getLineSet().createIterator();
   }
 
   @Override
   public final int getLineStartOffset(final int line) {
     if (line == 0) return 0; // otherwise it crashed for zero-length document
-    return myLineSet.getLineStart(line);
+    return getLineSet().getLineStart(line);
   }
 
   @Override
   public final int getLineEndOffset(int line) {
     if (getTextLength() == 0 && line == 0) return 0;
-    int result = myLineSet.getLineEnd(line) - getLineSeparatorLength(line);
+    int result = getLineSet().getLineEnd(line) - getLineSeparatorLength(line);
     assert result >= 0;
     return result;
   }
 
   @Override
   public final int getLineSeparatorLength(int line) {
-    int separatorLength = myLineSet.getSeparatorLength(line);
+    int separatorLength = getLineSet().getSeparatorLength(line);
     assert separatorLength >= 0;
     return separatorLength;
   }
 
   @Override
   public final int getLineCount() {
-    int lineCount = myLineSet.getLineCount();
+    int lineCount = getLineSet().getLineCount();
     assert lineCount >= 0;
     return lineCount;
   }
diff --git a/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java b/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java
index d621140..a0baadb 100644
--- a/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java
+++ b/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.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.
@@ -40,7 +40,6 @@
 import java.nio.charset.UnsupportedCharsetException;
 
 public final class LoadTextUtil {
-  private static final Key<String> DETECTED_LINE_SEPARATOR_KEY = Key.create("DETECTED_LINE_SEPARATOR_KEY");
   @Nls private static final String AUTO_DETECTED_FROM_BOM = "auto-detected from BOM";
 
   private LoadTextUtil() {
@@ -215,7 +214,7 @@
     }
     String newText = StringUtil.convertLineSeparators(currentText.toString(), newSeparator);
 
-    file.putUserData(DETECTED_LINE_SEPARATOR_KEY, newSeparator);
+    file.setDetectedLineSeparator(newSeparator);
     write(project, file, requestor, newText, -1);
   }
 
@@ -346,13 +345,7 @@
   @NotNull
   public static CharSequence loadText(@NotNull VirtualFile file) {
     if (file instanceof LightVirtualFile) {
-      CharSequence content = ((LightVirtualFile)file).getContent();
-      if (StringUtil.indexOf(content, '\r') == -1) return content;
-
-      CharBuffer buffer = CharBuffer.allocate(content.length());
-      buffer.append(content);
-      buffer.rewind();
-      return convertLineSeparators(buffer).first;
+      return ((LightVirtualFile)file).getContent();
     }
 
     if (file.isDirectory()) {
@@ -397,7 +390,7 @@
 
     Pair<CharSequence, String> result = convertBytes(bytes, charset, offset);
     if (saveDetectedSeparators) {
-      virtualFile.putUserData(DETECTED_LINE_SEPARATOR_KEY, result.getSecond());
+      virtualFile.setDetectedLineSeparator(result.getSecond());
     }
     return result.getFirst();
   }
@@ -425,7 +418,7 @@
   }
 
   static String getDetectedLineSeparator(@NotNull VirtualFile file) {
-    return file.getUserData(DETECTED_LINE_SEPARATOR_KEY);
+    return file.getDetectedLineSeparator();
   }
 
   @NotNull
diff --git a/platform/core-impl/src/com/intellij/openapi/module/impl/ModuleScopeProvider.java b/platform/core-impl/src/com/intellij/openapi/module/impl/ModuleScopeProvider.java
index 720c88d..58906e1 100644
--- a/platform/core-impl/src/com/intellij/openapi/module/impl/ModuleScopeProvider.java
+++ b/platform/core-impl/src/com/intellij/openapi/module/impl/ModuleScopeProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 
 
 import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Author: dmitrylomov
@@ -27,8 +28,10 @@
    *
    * @return scope including sources and tests, excluding libraries and dependencies.
    */
+  @NotNull
   GlobalSearchScope getModuleScope();
 
+  @NotNull
   GlobalSearchScope getModuleScope(boolean includeTests);
 
   /**
@@ -36,6 +39,7 @@
    *
    * @return scope including sources, tests, and libraries, excluding dependencies.
    */
+  @NotNull
   GlobalSearchScope getModuleWithLibrariesScope();
 
   /**
@@ -43,14 +47,21 @@
    *
    * @return scope including sources, tests, and dependencies, excluding libraries.
    */
+  @NotNull
   GlobalSearchScope getModuleWithDependenciesScope();
 
+  @NotNull
   GlobalSearchScope getModuleContentScope();
+  @NotNull
   GlobalSearchScope getModuleContentWithDependenciesScope();
 
+  @NotNull
   GlobalSearchScope getModuleWithDependenciesAndLibrariesScope(boolean includeTests);
+  @NotNull
   GlobalSearchScope getModuleWithDependentsScope();
+  @NotNull
   GlobalSearchScope getModuleTestsWithDependentsScope();
+  @NotNull
   GlobalSearchScope getModuleRuntimeScope(boolean includeTests);
 
   void clearCache();
diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/CoreJarVirtualFile.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/CoreJarVirtualFile.java
index 3827ecc..1256c54 100644
--- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/CoreJarVirtualFile.java
+++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/CoreJarVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -18,11 +18,13 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileSystem;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author yole
@@ -30,10 +32,10 @@
 public class CoreJarVirtualFile extends VirtualFile {
   private final CoreJarHandler myHandler;
   private final VirtualFile myParent;
-  private final ArrayList<VirtualFile> myChildren = new ArrayList<VirtualFile>();
+  private final List<VirtualFile> myChildren = new ArrayList<VirtualFile>();
   private final JarHandlerBase.EntryInfo myEntry;
 
-  public CoreJarVirtualFile(CoreJarHandler handler, JarHandlerBase.EntryInfo entry, CoreJarVirtualFile parent) {
+  public CoreJarVirtualFile(@NotNull CoreJarHandler handler, @NotNull JarHandlerBase.EntryInfo entry, @Nullable CoreJarVirtualFile parent) {
     myHandler = handler;
     myParent = parent;
     myEntry = entry;
@@ -56,6 +58,7 @@
   }
 
   @Override
+  @NotNull
   public String getPath() {
     if (myParent == null) return myHandler.myBasePath + "!/";
 
diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandlerBase.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandlerBase.java
index 4dba701..0648e3d 100644
--- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandlerBase.java
+++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandlerBase.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.
@@ -52,6 +52,7 @@
 
   protected static class EntryInfo {
     protected final boolean isDirectory;
+    @NotNull
     protected final String shortName;
     protected final EntryInfo parent;
 
diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java b/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java
index c3b770a..016cab9 100644
--- a/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java
+++ b/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -56,6 +56,7 @@
     return myFileSystem;
   }
 
+  @NotNull
   @Override
   public String getPath() {
     return FileUtil.toSystemIndependentName(myIoFile.getAbsolutePath());
diff --git a/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java b/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
index 5690078..26c87c7 100644
--- a/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
+++ b/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
@@ -24,10 +24,13 @@
 import com.intellij.openapi.util.ThrowableComputable;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.CheckinProjectPanel;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.FilePathImpl;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.NonFocusableCheckBox;
+import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -36,8 +39,9 @@
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.Collection;
-import java.util.LinkedHashSet;
+import java.io.File;
+import java.util.*;
+import java.util.List;
 
 /**
  * @author Nadya Zabrodina
@@ -51,6 +55,7 @@
   @Nullable private String myPreviousMessage;
   @Nullable private String myAmendedMessage;
   @NotNull protected final CheckinProjectPanel myCheckinPanel;
+  @Nullable  private  Map<VirtualFile, String> myMessagesForRoots;
 
   public DvcsCommitAdditionalComponent(@NotNull final Project project, @NotNull CheckinProjectPanel panel) {
     myCheckinPanel = panel;
@@ -76,14 +81,16 @@
       @Override
       public void actionPerformed(ActionEvent e) {
         if (myAmend.isSelected()) {
-          if (myPreviousMessage.equals(myCheckinPanel.getCommitMessage())) { // if user has already typed something, don't revert it
-            if (myAmendedMessage == null) {
-              loadMessageInModalTask(project);
+            if (myPreviousMessage.equals(myCheckinPanel.getCommitMessage())) { // if user has already typed something, don't revert it
+              if (myMessagesForRoots == null) {
+                loadMessagesInModalTask(project);      //load all commit messages for all repositories
+              }
+              String message = constructAmendedMessage();
+              if (!StringUtil.isEmptyOrSpaces(message)) {
+                myAmendedMessage = message;
+                substituteCommitMessage(myAmendedMessage);
+              }
             }
-            else { // checkbox is selected not the first time
-              substituteCommitMessage(myAmendedMessage);
-            }
-          }
         }
         else {
           // there was the amended message, but user has changed it => not reverting
@@ -96,6 +103,20 @@
     myPanel.add(myAmend, c);
   }
 
+  private String constructAmendedMessage() {
+    Set<VirtualFile> selectedRoots = getVcsRoots(getSelectedFilePaths());        // get only selected files
+    LinkedHashSet<String> messages = ContainerUtil.newLinkedHashSet();
+    if (myMessagesForRoots != null) {
+      for (VirtualFile root : selectedRoots) {
+        String message = myMessagesForRoots.get(root);
+        if (message != null) {
+          messages.add(message);
+        }
+      }
+    }
+    return DvcsUtil.joinMessagesOrNull(messages);
+  }
+
   public JComponent getComponent() {
     return myPanel;
   }
@@ -104,19 +125,15 @@
     myAmend.setSelected(false);
   }
 
-  private void loadMessageInModalTask(@NotNull Project project) {
+  private void loadMessagesInModalTask(@NotNull Project project) {
     try {
-      String messageFromVcs =
-        ProgressManager.getInstance().runProcessWithProgressSynchronously(new ThrowableComputable<String, VcsException>() {
+      myMessagesForRoots =
+        ProgressManager.getInstance().runProcessWithProgressSynchronously(new ThrowableComputable<Map<VirtualFile,String>, VcsException>() {
           @Override
-          public String compute() throws VcsException {
-            return getLastCommitMessage();
+          public Map<VirtualFile, String> compute() throws VcsException {
+            return getLastCommitMessages();
           }
         }, "Reading commit message...", false, project);
-      if (!StringUtil.isEmptyOrSpaces(messageFromVcs)) {
-        substituteCommitMessage(messageFromVcs);
-        myAmendedMessage = messageFromVcs;
-      }
     }
     catch (VcsException e) {
       Messages.showErrorDialog(getComponent(), "Couldn't load commit message of the commit to amend.\n" + e.getMessage(),
@@ -133,24 +150,32 @@
   }
 
   @Nullable
-  private String getLastCommitMessage() throws VcsException {
-    Collection<VirtualFile> roots = getRoots();
+  private Map<VirtualFile, String> getLastCommitMessages() throws VcsException {
+    Map<VirtualFile, String> messagesForRoots = new HashMap<VirtualFile, String>();
+    Collection<VirtualFile> roots = myCheckinPanel.getRoots(); //all committed vcs roots, not only selected
     final Ref<VcsException> exception = Ref.create();
-    LinkedHashSet<String> messages = ContainerUtil.newLinkedHashSet();
     for (VirtualFile root : roots) {
       String message = getLastCommitMessage(root);
-      if (message != null) {
-        messages.add(message);
-      }
+      messagesForRoots.put(root, message);
     }
     if (!exception.isNull()) {
       throw exception.get();
     }
-    return DvcsUtil.joinMessagesOrNull(messages);
+    return messagesForRoots;
   }
 
   @NotNull
-  protected abstract Collection<VirtualFile> getRoots();
+  private List<FilePath> getSelectedFilePaths() {
+    return ContainerUtil.map(myCheckinPanel.getFiles(), new Function<File, FilePath>() {
+      @Override
+      public FilePath fun(File file) {
+        return new FilePathImpl(file, file.isDirectory());
+      }
+    });
+  }
+
+  @NotNull
+  protected abstract Set<VirtualFile> getVcsRoots(@NotNull Collection<FilePath> files);
 
   @Nullable
   protected abstract String getLastCommitMessage(@NotNull VirtualFile repo) throws VcsException;
diff --git a/platform/dvcs/testFramework/com/intellij/dvcs/test/MockVirtualFile.java b/platform/dvcs/testFramework/com/intellij/dvcs/test/MockVirtualFile.java
index 2b6743c..3b36381 100644
--- a/platform/dvcs/testFramework/com/intellij/dvcs/test/MockVirtualFile.java
+++ b/platform/dvcs/testFramework/com/intellij/dvcs/test/MockVirtualFile.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.
@@ -39,9 +39,9 @@
  */
 public class MockVirtualFile extends VirtualFile {
 
-  private static VirtualFileSystem ourFileSystem = new MockVirtualFileSystem();
+  private static final VirtualFileSystem ourFileSystem = new MockVirtualFileSystem();
 
-  private String myPath;
+  private final String myPath;
 
   @NotNull
   static VirtualFile fromPath(@NotNull String absolutePath) {
@@ -84,6 +84,7 @@
     return ourFileSystem;
   }
 
+  @NotNull
   @Override
   public String getPath() {
     return myPath;
@@ -179,14 +180,12 @@
 
     MockVirtualFile file = (MockVirtualFile)o;
 
-    if (myPath != null ? !myPath.equals(file.myPath) : file.myPath != null) return false;
-
-    return true;
+    return myPath.equals(file.myPath);
   }
 
   @Override
   public int hashCode() {
-    return myPath != null ? myPath.hashCode() : 0;
+    return myPath.hashCode();
   }
 
 }
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java
index 7a6a0cf..1d15409 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java
@@ -21,13 +21,14 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.SmartList;
 import org.intellij.lang.annotations.JdkConstants;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Represents an entity that has a state, a presentation and can be performed.
@@ -143,9 +144,10 @@
   public final void registerCustomShortcutSet(@NotNull ShortcutSet shortcutSet, @Nullable JComponent component){
     myShortcutSet = shortcutSet;
     if (component != null){
-      @SuppressWarnings("unchecked") ArrayList<AnAction> actionList = (ArrayList<AnAction>)component.getClientProperty(ourClientProperty);
+      @SuppressWarnings("unchecked")
+      List<AnAction> actionList = (List<AnAction>)component.getClientProperty(ourClientProperty);
       if (actionList == null){
-        actionList = new ArrayList<AnAction>(1);
+        actionList = new SmartList<AnAction>();
         component.putClientProperty(ourClientProperty, actionList);
       }
       if (!actionList.contains(this)){
@@ -170,7 +172,8 @@
 
   public final void unregisterCustomShortcutSet(JComponent component){
     if (component != null){
-      @SuppressWarnings("unchecked") ArrayList<AnAction> actionList = (ArrayList<AnAction>)component.getClientProperty(ourClientProperty);
+      @SuppressWarnings("unchecked")
+      List<AnAction> actionList = (List<AnAction>)component.getClientProperty(ourClientProperty);
       if (actionList != null){
         actionList.remove(this);
       }
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/Caret.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/Caret.java
index 3648e47..43b5e75 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/Caret.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/Caret.java
@@ -202,6 +202,8 @@
    * Selects target range providing information about visual boundary of selection end.
    * <p/>
    * That is the case for soft wraps-aware processing where the whole soft wraps virtual space is matched to the same offset.
+   * <p/>
+   * Also, in column mode this method allows to create selection spanning virtual space after the line end.
    *
    * @param startOffset     start selection offset
    * @param endPosition     end visual position of the text range to select (<code>null</code> argument means that
@@ -214,6 +216,8 @@
    * Selects target range based on its visual boundaries.
    * <p/>
    * That is the case for soft wraps-aware processing where the whole soft wraps virtual space is matched to the same offset.
+   * <p/>
+   * Also, in column mode this method allows to create selection spanning virtual space after the line end.
    *
    * @param startPosition   start visual position of the text range to select (<code>null</code> argument means that
    *                        no specific visual position should be used)
@@ -249,8 +253,8 @@
    * selection will be set for the new caret.
    *
    * @param above if <code>true</code>, new caret will be created at the previous line, if <code>false</code> - on the next line
-   * @return newly created caret instance, or null if the caret cannot be created because it already exists at the new location or caret
-   * model doesn't support multiple carets.
+   * @return newly created caret instance, or <code>null</code> if the caret cannot be created because it already exists at the new location
+   * or caret model doesn't support multiple carets.
    */
   @Nullable
   Caret clone(boolean above);
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/CaretModel.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/CaretModel.java
index 17ddb3f..1d26b77 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/CaretModel.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/CaretModel.java
@@ -17,7 +17,6 @@
 
 import com.intellij.openapi.editor.event.CaretListener;
 import com.intellij.openapi.editor.markup.TextAttributes;
-import com.intellij.openapi.util.Segment;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -130,14 +129,14 @@
   int getOffset();
 
   /**
-   * Adds a listener for receiving notifications about caret movement.
+   * Adds a listener for receiving notifications about caret movement and caret addition/removal
    *
    * @param listener the listener instance.
    */
   void addCaretListener(@NotNull CaretListener listener);
 
   /**
-   * Removes a listener for receiving notifications about caret movement.
+   * Removes a listener for receiving notifications about caret movement and caret addition/removal
    *
    * @param listener the listener instance.
    */
@@ -182,6 +181,11 @@
   Caret getPrimaryCaret();
 
   /**
+   * Returns number of carets currently existing in the document
+   */
+  int getCaretCount();
+
+  /**
    * Returns all carets currently existing in the document, ordered by their position in the document.
    */
   @NotNull
@@ -214,14 +218,14 @@
   void removeSecondaryCarets();
 
   /**
-   * Sets the number of carets, their positions and selection ranges according to the provided parameters. Null values in any of the
-   * collections will mean that corresponding caret's position and/or selection won't be changed.
+   * Sets the number of carets, their positions and selection ranges according to the provided data. Null values for caret position or
+   * selection boundaries will mean that corresponding caret's position and/or selection won't be changed.
    * <p>
    * If multiple carets are not supported, the behaviour is unspecified.
    *
    * @see #supportsMultipleCarets()
    */
-  void setCaretsAndSelections(@NotNull List<LogicalPosition> caretPositions, @NotNull List<? extends Segment> selections);
+  void setCaretsAndSelections(@NotNull List<CaretState> caretStates);
 
   /**
    * Executes the given task for each existing caret. Carets are iterated in their position order. Set of carets to iterate over is
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/CaretState.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/CaretState.java
new file mode 100644
index 0000000..d7588f1
--- /dev/null
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/CaretState.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor;
+
+import org.jetbrains.annotations.Nullable;
+
+public class CaretState {
+  private final LogicalPosition caretPosition;
+  private final LogicalPosition selectionStart;
+  private final LogicalPosition selectionEnd;
+
+  public CaretState(@Nullable LogicalPosition position, @Nullable LogicalPosition start, @Nullable LogicalPosition end) {
+    caretPosition = position;
+    selectionStart = start;
+    selectionEnd = end;
+  }
+
+  @Nullable
+  public LogicalPosition getCaretPosition(){
+    return caretPosition;
+  }
+
+  @Nullable
+  public LogicalPosition getSelectionStart() {
+    return selectionStart;
+  }
+
+  @Nullable
+  public LogicalPosition getSelectionEnd() {
+    return selectionEnd;
+  }
+
+  @Override
+  public String toString() {
+    return "CaretState{" +
+           "caretPosition=" + caretPosition +
+           ", selectionStart=" + selectionStart +
+           ", selectionEnd=" + selectionEnd +
+           '}';
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretAdapter.java
similarity index 61%
copy from platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
copy to platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretAdapter.java
index 72c585b..86b2bac 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretAdapter.java
@@ -13,18 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk2;
+package com.intellij.openapi.editor.event;
 
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.util.Consumer;
+public abstract class CaretAdapter implements CaretListener {
+  @Override
+  public void caretPositionChanged(CaretEvent e) {
+  }
 
-/**
- * @author traff
- */
-public interface RemoteSdkProducer<T extends RemoteSdkCredentials> {
-  T getRemoteSdkCredentials() throws InterruptedException;
-  
-  void produceRemoteSdkCredentials(Consumer<T> remoteSdkConsumer);
+  @Override
+  public void caretAdded(CaretEvent e) {
+  }
 
-  Object getRemoteSdkDataKey();
+  @Override
+  public void caretRemoved(CaretEvent e) {
+  }
 }
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretListener.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretListener.java
index d99649c..fe73fc1 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretListener.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretListener.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.
@@ -18,7 +18,7 @@
 import java.util.EventListener;
 
 /**
- * Allows to receive notifications about caret movement.
+ * Allows to receive notifications about caret movement, and caret additions/removal
  *
  * @see com.intellij.openapi.editor.CaretModel#addCaretListener(CaretListener)
  * @see EditorEventMulticaster#addCaretListener(CaretListener)
@@ -30,4 +30,14 @@
    * @param e the event containing information about the caret movement.
    */
   void caretPositionChanged(CaretEvent e);
+
+  /**
+   * Called when a new caret was added to the document.
+   */
+  void caretAdded(CaretEvent e);
+
+  /**
+   * Called when a caret was removed from the document.
+   */
+  void caretRemoved(CaretEvent e);
 }
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/event/MultipleCaretListener.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/event/MultipleCaretListener.java
deleted file mode 100644
index 0c225cf..0000000
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/event/MultipleCaretListener.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.editor.event;
-
-/**
- * In addition to caret movement event received by CaretListener instances, these listeners will also get caret creation/destroying events.
- *
- * @see CaretListener
- * @see com.intellij.openapi.editor.CaretModel#addCaretListener(CaretListener)
- * @see EditorEventMulticaster#addCaretListener(CaretListener)
- */
-public interface MultipleCaretListener extends CaretListener {
-  /**
-   * Called when a new caret was added to the document.
-   */
-  void caretAdded(CaretEvent e);
-
-  /**
-   * Called when a caret was removed from the document.
-   */
-  void caretRemoved(CaretEvent e);
-}
diff --git a/platform/editor-ui-ex/src/com/intellij/injected/editor/MarkupModelWindow.java b/platform/editor-ui-ex/src/com/intellij/injected/editor/MarkupModelWindow.java
index b11ff74..9fd7227 100644
--- a/platform/editor-ui-ex/src/com/intellij/injected/editor/MarkupModelWindow.java
+++ b/platform/editor-ui-ex/src/com/intellij/injected/editor/MarkupModelWindow.java
@@ -110,7 +110,7 @@
   }
 
   @Override
-  public RangeHighlighter addPersistentLineHighlighter(final int line, final int layer, final TextAttributes textAttributes) {
+  public RangeHighlighterEx addPersistentLineHighlighter(final int line, final int layer, final TextAttributes textAttributes) {
     int hostLine = myDocument.injectedToHostLine(line);
     return myHostModel.addPersistentLineHighlighter(hostLine, layer, textAttributes);
   }
diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/MarkupModelEx.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/MarkupModelEx.java
index 284ef90..28d8cb4 100644
--- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/MarkupModelEx.java
+++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/MarkupModelEx.java
@@ -33,7 +33,7 @@
   void dispose();
 
   @Nullable
-  RangeHighlighter addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes);
+  RangeHighlighterEx addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes);
 
   void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter, boolean renderersChanged);
 
diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/EmptyMarkupModel.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/EmptyMarkupModel.java
index d9e5c4b..a3ac344 100644
--- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/EmptyMarkupModel.java
+++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/EmptyMarkupModel.java
@@ -109,7 +109,7 @@
   }
 
   @Override
-  public RangeHighlighter addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes) {
+  public RangeHighlighterEx addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes) {
     return null;
   }
 
diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java
index 50a9922..5724189 100644
--- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java
+++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java
@@ -76,13 +76,13 @@
 
   @Override
   @Nullable
-  public RangeHighlighter addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes) {
+  public RangeHighlighterEx addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes) {
     if (isNotValidLine(lineNumber)) {
       return null;
     }
 
     int offset = getFirstNonSpaceCharOffset(getDocument(), lineNumber);
-    return addRangeHighlighter(PersistentRangeHighlighterImpl.create(this, offset, layer, HighlighterTargetArea.LINES_IN_RANGE, null, false), null);
+    return addRangeHighlighter(PersistentRangeHighlighterImpl.create(this, offset, layer, HighlighterTargetArea.LINES_IN_RANGE, textAttributes, false), null);
   }
 
   private boolean isNotValidLine(int lineNumber) {
diff --git a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java
index dca89ac..08eab82 100644
--- a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java
+++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -70,13 +70,13 @@
     }
 
     @Override
-    public void save(final DataOutput out, final TodoIndexEntry value) throws IOException {
+    public void save(@NotNull final DataOutput out, final TodoIndexEntry value) throws IOException {
       out.writeUTF(value.pattern);
       out.writeBoolean(value.caseSensitive);
     }
 
     @Override
-    public TodoIndexEntry read(final DataInput in) throws IOException {
+    public TodoIndexEntry read(@NotNull final DataInput in) throws IOException {
       final String pattern = in.readUTF();
       final boolean caseSensitive = in.readBoolean();
       return new TodoIndexEntry(pattern, caseSensitive);
@@ -106,7 +106,7 @@
   
   private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
     @Override
-    public boolean acceptInput(final VirtualFile file) {
+    public boolean acceptInput(@NotNull final VirtualFile file) {
       if (!file.isInLocalFileSystem()) {
         return false; // do not index TODOs in library sources
       }
@@ -147,16 +147,19 @@
     return myIndexer;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<TodoIndexEntry> getKeyDescriptor() {
     return myKeyDescriptor;
   }
 
+  @NotNull
   @Override
   public DataExternalizer<Integer> getValueExternalizer() {
     return myValueExternalizer;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return myInputFilter;
diff --git a/platform/icons/src/nodes/pluginJB.png b/platform/icons/src/nodes/pluginJB.png
new file mode 100644
index 0000000..54b0361
--- /dev/null
+++ b/platform/icons/src/nodes/pluginJB.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginJB@2x.png b/platform/icons/src/nodes/pluginJB@2x.png
new file mode 100644
index 0000000..dbaac8f
--- /dev/null
+++ b/platform/icons/src/nodes/pluginJB@2x.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginJB@2x_dark.png b/platform/icons/src/nodes/pluginJB@2x_dark.png
new file mode 100644
index 0000000..6af3191
--- /dev/null
+++ b/platform/icons/src/nodes/pluginJB@2x_dark.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginJB_dark.png b/platform/icons/src/nodes/pluginJB_dark.png
new file mode 100644
index 0000000..7325cf7
--- /dev/null
+++ b/platform/icons/src/nodes/pluginJB_dark.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginRestart.png b/platform/icons/src/nodes/pluginRestart.png
new file mode 100644
index 0000000..a47d933
--- /dev/null
+++ b/platform/icons/src/nodes/pluginRestart.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginRestart@2x.png b/platform/icons/src/nodes/pluginRestart@2x.png
new file mode 100644
index 0000000..3c9e05c
--- /dev/null
+++ b/platform/icons/src/nodes/pluginRestart@2x.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginRestart@2x_dark.png b/platform/icons/src/nodes/pluginRestart@2x_dark.png
new file mode 100644
index 0000000..4c4439c
--- /dev/null
+++ b/platform/icons/src/nodes/pluginRestart@2x_dark.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginRestart_dark.png b/platform/icons/src/nodes/pluginRestart_dark.png
new file mode 100644
index 0000000..c0cc12a
--- /dev/null
+++ b/platform/icons/src/nodes/pluginRestart_dark.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginUpdate.png b/platform/icons/src/nodes/pluginUpdate.png
new file mode 100644
index 0000000..62f0a4f
--- /dev/null
+++ b/platform/icons/src/nodes/pluginUpdate.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginUpdate@2x.png b/platform/icons/src/nodes/pluginUpdate@2x.png
new file mode 100644
index 0000000..b0b65f1
--- /dev/null
+++ b/platform/icons/src/nodes/pluginUpdate@2x.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginUpdate@2x_dark.png b/platform/icons/src/nodes/pluginUpdate@2x_dark.png
new file mode 100644
index 0000000..8801cf2
--- /dev/null
+++ b/platform/icons/src/nodes/pluginUpdate@2x_dark.png
Binary files differ
diff --git a/platform/icons/src/nodes/pluginUpdate_dark.png b/platform/icons/src/nodes/pluginUpdate_dark.png
new file mode 100644
index 0000000..aa051df
--- /dev/null
+++ b/platform/icons/src/nodes/pluginUpdate_dark.png
Binary files differ
diff --git a/platform/indexing-api/src/com/intellij/util/indexing/DefaultFileTypeSpecificInputFilter.java b/platform/indexing-api/src/com/intellij/util/indexing/DefaultFileTypeSpecificInputFilter.java
index 6273968..903c5c4 100644
--- a/platform/indexing-api/src/com/intellij/util/indexing/DefaultFileTypeSpecificInputFilter.java
+++ b/platform/indexing-api/src/com/intellij/util/indexing/DefaultFileTypeSpecificInputFilter.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.
@@ -32,7 +32,7 @@
   }
 
   @Override
-  public boolean acceptInput(VirtualFile file) {
+  public boolean acceptInput(@NotNull VirtualFile file) {
     return true;
   }
 }
diff --git a/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndex.java
index 3cdb853..6628f3c 100644
--- a/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndex.java
+++ b/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -137,7 +137,7 @@
    * @param project it is guaranteed to return data which is up-to-date withing the project
    *                Keys obtained from the files which do not belong to the project specified may not be up-to-date or even exist
    */
-  public abstract <K> boolean processAllKeys(@NotNull ID<K, ?> indexId, Processor<K> processor, @Nullable Project project);
+  public abstract <K> boolean processAllKeys(@NotNull ID<K, ?> indexId, @NotNull Processor<K> processor, @Nullable Project project);
 
   public <K> boolean processAllKeys(@NotNull ID<K, ?> indexId, @NotNull Processor<K> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter idFilter) {
     return processAllKeys(indexId, processor, scope.getProject());
@@ -156,7 +156,7 @@
   * Author: dmitrylomov
   */
   public interface InputFilter {
-    boolean acceptInput(VirtualFile file);
+    boolean acceptInput(@NotNull VirtualFile file);
   }
 
   public interface FileTypeSpecificInputFilter extends InputFilter {
diff --git a/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java b/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java
index 91d9470..dc60919 100644
--- a/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java
+++ b/platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -39,11 +39,14 @@
 
   @NotNull
   public abstract DataIndexer<K, V, FileContent> getIndexer();
-  
+
+  @NotNull
   public abstract KeyDescriptor<K> getKeyDescriptor();
-  
+
+  @NotNull
   public abstract DataExternalizer<V> getValueExternalizer();
-  
+
+  @NotNull
   public abstract FileBasedIndex.InputFilter getInputFilter();
   
   public abstract boolean dependsOnFileContent();
diff --git a/platform/indexing-impl/src/com/intellij/openapi/module/impl/ModuleScopeProviderImpl.java b/platform/indexing-impl/src/com/intellij/openapi/module/impl/ModuleScopeProviderImpl.java
index f90fe78..052c730 100644
--- a/platform/indexing-impl/src/com/intellij/openapi/module/impl/ModuleScopeProviderImpl.java
+++ b/platform/indexing-impl/src/com/intellij/openapi/module/impl/ModuleScopeProviderImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,8 +31,7 @@
   private GlobalSearchScope myModuleWithDependentsScope;
   private GlobalSearchScope myModuleTestsWithDependentsScope;
 
-
-  public ModuleScopeProviderImpl(Module module) {
+  public ModuleScopeProviderImpl(@NotNull Module module) {
     myModule = module;
   }
 
@@ -47,53 +46,72 @@
   }
 
 
+  @Override
+  @NotNull
   public GlobalSearchScope getModuleScope() {
     return getCachedScope(ModuleWithDependenciesScope.COMPILE | ModuleWithDependenciesScope.TESTS);
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleScope(boolean includeTests) {
     return getCachedScope(ModuleWithDependenciesScope.COMPILE | (includeTests ? ModuleWithDependenciesScope.TESTS : 0));
   }
 
+  @Override
+  @NotNull
   public GlobalSearchScope getModuleWithLibrariesScope() {
     return getCachedScope(ModuleWithDependenciesScope.COMPILE | ModuleWithDependenciesScope.TESTS | ModuleWithDependenciesScope.LIBRARIES);
   }
 
+  @Override
+  @NotNull
   public GlobalSearchScope getModuleWithDependenciesScope() {
     return getCachedScope(ModuleWithDependenciesScope.COMPILE | ModuleWithDependenciesScope.TESTS | ModuleWithDependenciesScope.MODULES);
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleContentScope() {
     return getCachedScope(ModuleWithDependenciesScope.CONTENT);
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleContentWithDependenciesScope() {
     return getCachedScope(ModuleWithDependenciesScope.CONTENT | ModuleWithDependenciesScope.MODULES);
   }
 
+  @Override
+  @NotNull
   public GlobalSearchScope getModuleWithDependenciesAndLibrariesScope(boolean includeTests) {
     return getCachedScope(ModuleWithDependenciesScope.COMPILE |
                           ModuleWithDependenciesScope.MODULES |
                           ModuleWithDependenciesScope.LIBRARIES | (includeTests ? ModuleWithDependenciesScope.TESTS : 0));
   }
 
+  @Override
+  @NotNull
   public GlobalSearchScope getModuleWithDependentsScope() {
-    if (myModuleWithDependentsScope == null) {
-      myModuleWithDependentsScope = new ModuleWithDependentsScope(myModule, false);
+    GlobalSearchScope scope = myModuleWithDependentsScope;
+    if (scope == null) {
+      myModuleWithDependentsScope = scope = new ModuleWithDependentsScope(myModule, false);
     }
-    return myModuleWithDependentsScope;
+    return scope;
   }
 
+  @Override
+  @NotNull
   public GlobalSearchScope getModuleTestsWithDependentsScope() {
-    if (myModuleTestsWithDependentsScope == null) {
-      myModuleTestsWithDependentsScope = new ModuleWithDependentsScope(myModule, true);
+    GlobalSearchScope scope = myModuleTestsWithDependentsScope;
+    if (scope == null) {
+      myModuleTestsWithDependentsScope = scope = new ModuleWithDependentsScope(myModule, true);
     }
-    return myModuleTestsWithDependentsScope;
+    return scope;
   }
 
+  @Override
+  @NotNull
   public GlobalSearchScope getModuleRuntimeScope(boolean includeTests) {
     return getCachedScope(
       ModuleWithDependenciesScope.MODULES | ModuleWithDependenciesScope.LIBRARIES | (includeTests ? ModuleWithDependenciesScope.TESTS : 0));
diff --git a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependenciesScope.java b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependenciesScope.java
index 0839c80..477a04f 100644
--- a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependenciesScope.java
+++ b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependenciesScope.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.
@@ -54,7 +54,7 @@
   private final Set<Module> myModules;
   private final TObjectIntHashMap<VirtualFile> myRoots = new TObjectIntHashMap<VirtualFile>();
 
-  public ModuleWithDependenciesScope(Module module, @ScopeConstant int options) {
+  public ModuleWithDependenciesScope(@NotNull Module module, @ScopeConstant int options) {
     super(module.getProject());
     myModule = module;
     myOptions = options;
diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndex.java b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndex.java
index 4ad94f5..3e96882 100644
--- a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndex.java
+++ b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -43,19 +43,19 @@
   
   private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
     @Override
-    public boolean acceptInput(final VirtualFile file) {
+    public boolean acceptInput(@NotNull final VirtualFile file) {
       return isIndexable(file.getFileType());
     }
   };
 
   private final DataExternalizer<Integer> myValueExternalizer = new DataExternalizer<Integer>() {
     @Override
-    public void save(final DataOutput out, final Integer value) throws IOException {
+    public void save(@NotNull final DataOutput out, final Integer value) throws IOException {
       out.writeByte(value.intValue());
     }
 
     @Override
-    public Integer read(final DataInput in) throws IOException {
+    public Integer read(@NotNull final DataInput in) throws IOException {
       return Integer.valueOf(in.readByte());
     }
   };
@@ -107,16 +107,19 @@
     return myIndexer;
   }
 
+  @NotNull
   @Override
   public DataExternalizer<Integer> getValueExternalizer() {
     return myValueExternalizer;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<IdIndexEntry> getKeyDescriptor() {
     return myKeyDescriptor;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return myInputFilter;
diff --git a/platform/indexing-impl/src/com/intellij/psi/search/FileTypeIndex.java b/platform/indexing-impl/src/com/intellij/psi/search/FileTypeIndex.java
index b0a8673..061100b 100644
--- a/platform/indexing-impl/src/com/intellij/psi/search/FileTypeIndex.java
+++ b/platform/indexing-impl/src/com/intellij/psi/search/FileTypeIndex.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.psi.search;
 
 import com.intellij.openapi.fileTypes.FileType;
@@ -47,11 +62,13 @@
     return this;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<FileType> getKeyDescriptor() {
     return this;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return this;
@@ -73,17 +90,17 @@
   }
 
   @Override
-  public boolean acceptInput(VirtualFile file) {
+  public boolean acceptInput(@NotNull VirtualFile file) {
     return !file.isDirectory();
   }
 
   @Override
-  public void save(DataOutput out, FileType value) throws IOException {
+  public void save(@NotNull DataOutput out, FileType value) throws IOException {
     myEnumeratorStringDescriptor.save(out, value.getName());
   }
 
   @Override
-  public FileType read(DataInput in) throws IOException {
+  public FileType read(@NotNull DataInput in) throws IOException {
     String read = myEnumeratorStringDescriptor.read(in);
     return myFileTypeManager.findFileTypeByName(read);
   }
diff --git a/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java b/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java
index 7c42954..0e95aef 100644
--- a/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.java
+++ b/platform/indexing-impl/src/com/intellij/psi/search/FilenameIndex.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.
@@ -54,11 +54,13 @@
     return myDataIndexer;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<String> getKeyDescriptor() {
     return myKeyDescriptor;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return myInputFilter;
@@ -156,7 +158,7 @@
 
   private static class MyInputFilter implements FileBasedIndex.InputFilter {
     @Override
-    public boolean acceptInput(final VirtualFile file) {
+    public boolean acceptInput(@NotNull final VirtualFile file) {
       return true;
     }
   }
diff --git a/platform/indexing-impl/src/com/intellij/util/indexing/ScalarIndexExtension.java b/platform/indexing-impl/src/com/intellij/util/indexing/ScalarIndexExtension.java
index df15500..3832141 100644
--- a/platform/indexing-impl/src/com/intellij/util/indexing/ScalarIndexExtension.java
+++ b/platform/indexing-impl/src/com/intellij/util/indexing/ScalarIndexExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -17,6 +17,7 @@
 package com.intellij.util.indexing;
 
 import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.DataInput;
@@ -31,6 +32,7 @@
 
   public static final DataExternalizer<Void> VOID_DATA_EXTERNALIZER = new VoidDataExternalizer();
 
+  @NotNull
   @Override
   public final DataExternalizer<Void> getValueExternalizer() {
     return VOID_DATA_EXTERNALIZER;
@@ -39,12 +41,12 @@
   private static class VoidDataExternalizer implements DataExternalizer<Void> {
 
     @Override
-    public void save(final DataOutput out, final Void value) throws IOException {
+    public void save(@NotNull final DataOutput out, final Void value) throws IOException {
     }
 
     @Override
     @Nullable
-    public Void read(final DataInput in) throws IOException {
+    public Void read(@NotNull final DataInput in) throws IOException {
       return null;
     }
   }
diff --git a/platform/indexing-impl/src/com/intellij/util/indexing/SingleEntryFileBasedIndexExtension.java b/platform/indexing-impl/src/com/intellij/util/indexing/SingleEntryFileBasedIndexExtension.java
index 128d7d4..1e111b2 100644
--- a/platform/indexing-impl/src/com/intellij/util/indexing/SingleEntryFileBasedIndexExtension.java
+++ b/platform/indexing-impl/src/com/intellij/util/indexing/SingleEntryFileBasedIndexExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -27,6 +27,7 @@
  *         Date: Feb 18, 2009
  */
 public abstract class SingleEntryFileBasedIndexExtension<V> extends FileBasedIndexExtension<Integer, V>{
+  @NotNull
   @Override
   public final KeyDescriptor<Integer> getKeyDescriptor() {
     return EnumeratorIntegerDescriptor.INSTANCE;
diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ClickNavigator.java b/platform/lang-impl/src/com/intellij/application/options/colors/ClickNavigator.java
index 464bf03..df10c20 100644
--- a/platform/lang-impl/src/com/intellij/application/options/colors/ClickNavigator.java
+++ b/platform/lang-impl/src/com/intellij/application/options/colors/ClickNavigator.java
@@ -1,6 +1,5 @@
 /*
-/*
- * Copyright 2000-2009 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.
@@ -25,6 +24,7 @@
 import com.intellij.openapi.editor.HighlighterColors;
 import com.intellij.openapi.editor.LogicalPosition;
 import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.editor.event.CaretAdapter;
 import com.intellij.openapi.editor.event.CaretEvent;
 import com.intellij.openapi.editor.event.CaretListener;
 import com.intellij.openapi.editor.ex.EditorEx;
@@ -56,7 +56,7 @@
       }
     });
 
-    CaretListener listener = new CaretListener() {
+    CaretListener listener = new CaretAdapter() {
       @Override
       public void caretPositionChanged(CaretEvent e) {
         setSelectedItem(HighlighterColors.TEXT.getExternalName(), true);
@@ -98,7 +98,7 @@
                                 final boolean isBackgroundImportant) {
     addMouseMotionListener(view, highlighter, data, isBackgroundImportant);
 
-    CaretListener listener = new CaretListener() {
+    CaretListener listener = new CaretAdapter() {
       @Override
       public void caretPositionChanged(CaretEvent e) {
         navigate(view, true, e.getNewPosition(), highlighter, data, isBackgroundImportant);
diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/SimpleEditorPreview.java b/platform/lang-impl/src/com/intellij/application/options/colors/SimpleEditorPreview.java
index 6daa2db..e7e92ca 100644
--- a/platform/lang-impl/src/com/intellij/application/options/colors/SimpleEditorPreview.java
+++ b/platform/lang-impl/src/com/intellij/application/options/colors/SimpleEditorPreview.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
 import com.intellij.openapi.editor.colors.CodeInsightColors;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.editor.event.CaretAdapter;
 import com.intellij.openapi.editor.event.CaretEvent;
 import com.intellij.openapi.editor.event.CaretListener;
 import com.intellij.openapi.editor.ex.EditorEx;
@@ -80,7 +81,7 @@
     if (navigatable) {
       addMouseMotionListener(myEditor, page.getHighlighter(), myHighlightData, false);
 
-      CaretListener listener = new CaretListener() {
+      CaretListener listener = new CaretAdapter() {
         @Override
         public void caretPositionChanged(CaretEvent e) {
           navigate(myEditor, true, e.getNewPosition(), page.getHighlighter(), myHighlightData, false);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
index a721c6f..392e35a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
@@ -622,20 +622,26 @@
         marker.dispose();
       }
 
-    } else {
-      final Ref<CompletionAssertions.WatchingInsertionContext> contextRef = new Ref<CompletionAssertions.WatchingInsertionContext>();
-      final Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
+    } else if (editor.getCaretModel().supportsMultipleCarets()) {
+      final List<CompletionAssertions.WatchingInsertionContext> contexts = new ArrayList<CompletionAssertions.WatchingInsertionContext>();
       editor.getCaretModel().runForEachCaret(new CaretAction() {
         @Override
         public void perform(Caret caret) {
           CompletionAssertions.WatchingInsertionContext currentContext = insertItem(indicator, item, completionChar, items, update, editor,
                                                                                     caret.getOffset(), caret.getOffset() + idEndOffsetDelta);
-          if (caret == primaryCaret) {
-            contextRef.set(currentContext);
-          }
+          contexts.add(currentContext);
         }
       });
-      context = contextRef.get();
+      context = contexts.get(contexts.size() - 1);
+      if (context.shouldAddCompletionChar() && context.getCompletionChar() != Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
+        DataContext dataContext = DataManager.getInstance().getDataContext(editor.getContentComponent());
+        EditorActionManager.getInstance().getTypedAction().getHandler().execute(editor, completionChar, dataContext);
+      }
+      for (CompletionAssertions.WatchingInsertionContext insertionContext : contexts) {
+        insertionContext.stopWatching();
+      }
+    } else {
+      context = insertItem(indicator, item, completionChar, items, update, editor, caretOffset, idEndOffset);
     }
     return context;
   }
@@ -719,7 +725,9 @@
         if (context.shouldAddCompletionChar()) {
           addCompletionChar(project, context, item, editor, indicator, completionChar);
         }
-        context.stopWatching();
+        if (!editor.getCaretModel().supportsMultipleCarets()) { // done later, outside of this method
+          context.stopWatching();
+        }
         editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
       }
     });
@@ -747,7 +755,7 @@
         }
       }
     }
-    else {
+    else if (!editor.getCaretModel().supportsMultipleCarets()) { // this will be done outside of runForEach caret context
       DataContext dataContext = DataManager.getInstance().getDataContext(editor.getContentComponent());
       EditorActionManager.getInstance().getTypedAction().getHandler().execute(editor, completionChar, dataContext);
     }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java
index 6ba44fd..d135e19 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -253,7 +253,7 @@
           CompletionServiceImpl.setCompletionPhase(NoCompletion);
         }
       };
-      final CaretListener caretListener = new CaretListener() {
+      final CaretListener caretListener = new CaretAdapter() {
         @Override
         public void caretPositionChanged(CaretEvent e) {
           CompletionServiceImpl.setCompletionPhase(NoCompletion);
@@ -341,7 +341,7 @@
         }
       };
 
-      caretListener = new CaretListener() {
+      caretListener = new CaretAdapter() {
         @Override
         public void caretPositionChanged(CaretEvent e) {
           if (!TypedAction.isTypedActionInProgress()) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java
index d20e481..b33a029 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java
@@ -176,7 +176,7 @@
       }
     }, this);
 
-    eventMulticaster.addCaretListener(new CaretListener() {
+    eventMulticaster.addCaretListener(new CaretAdapter() {
       @Override
       public void caretPositionChanged(CaretEvent e) {
         final Editor editor = e.getEditor();
@@ -184,17 +184,17 @@
             !worthBothering(editor.getDocument(), editor.getProject())) {
           return; //no need to stop daemon if something happened in the console
         }
-
-        ApplicationManager.getApplication().invokeLater(new Runnable() {
-          @Override
-          public void run() {
-            if (!editor.getComponent().isShowing() && !application.isUnitTestMode() ||
-                myProject.isDisposed()) {
-              return;
+        if (!application.isUnitTestMode()) {
+          ApplicationManager.getApplication().invokeLater(new Runnable() {
+            @Override
+            public void run() {
+              if (!editor.getComponent().isShowing() || myProject.isDisposed()) {
+                return;
+              }
+              myDaemonCodeAnalyzer.hideLastIntentionHint();
             }
-            myDaemonCodeAnalyzer.hideLastIntentionHint();
-          }
-        }, ModalityState.current());
+          }, ModalityState.current());
+        }
       }
     }, this);
 
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java
index 89e8b55..199f667 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.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.
@@ -354,7 +354,7 @@
     }
   }
   
-  private class MyCaretListener implements CaretListener {
+  private class MyCaretListener extends CaretAdapter {
     @Override
     public void caretPositionChanged(CaretEvent e) {
       allowUpdateFromContext(true);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java
index 9c15f4f..0296e8e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java
@@ -90,7 +90,7 @@
 
     final Project project = editor.getProject();
     if (project == null || editor.isColumnMode() || editor.getSelectionModel().hasBlockSelection()
-        || editor.getCaretModel().getAllCarets().size() > 1) {
+        || editor.getCaretModel().getCaretCount() > 1) {
       if (myOriginalHandler != null) {
         myOriginalHandler.execute(editor, context);
       }
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
index 216227d..259fe97 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
@@ -135,10 +135,7 @@
     Project project = CommonDataKeys.PROJECT.getData(dataContext);
     PsiFile file;
 
-    if (project == null
-        || editor.isColumnMode()
-        || editor.getCaretModel().getAllCarets().size() > 1
-        || (file = PsiUtilBase.getPsiFileInEditor(editor, project)) == null) {
+    if (project == null || editor.isColumnMode() || (file = PsiUtilBase.getPsiFileInEditor(editor, project)) == null) {
       if (myOriginalHandler != null){
         myOriginalHandler.execute(editor, charTyped, dataContext);
       }
@@ -174,13 +171,13 @@
     }
 
     if (!editor.isInsertMode()){
-      myOriginalHandler.execute(originalEditor, charTyped, dataContext);
+      if (myOriginalHandler != null) {
+        myOriginalHandler.execute(originalEditor, charTyped, dataContext);
+      }
       return;
     }
 
-    if (editor.getSelectionModel().hasSelection()){
-      EditorModificationUtil.deleteSelectedText(editor);
-    }
+    EditorModificationUtil.deleteSelectedTextForAllCarets(editor);
 
     FileType fileType = getFileType(file, editor);
 
@@ -194,7 +191,7 @@
       }
     }
 
-    if (!editor.getSelectionModel().hasBlockSelection()) {
+    if (!editor.getSelectionModel().hasBlockSelection() && editor.getCaretModel().getCaretCount() == 1) {
       if (')' == charTyped || ']' == charTyped || '}' == charTyped) {
         if (FileTypes.PLAIN_TEXT != fileType) {
           if (handleRParen(editor, fileType, charTyped)) return;
@@ -206,12 +203,14 @@
     }
 
     long modificationStampBeforeTyping = editor.getDocument().getModificationStamp();
-    myOriginalHandler.execute(originalEditor, charTyped, dataContext);
+    if (myOriginalHandler != null) {
+      myOriginalHandler.execute(originalEditor, charTyped, dataContext);
+    }
     AutoHardWrapHandler.getInstance().wrapLineIfNecessary(editor, dataContext, modificationStampBeforeTyping);
 
     if (('(' == charTyped || '[' == charTyped || '{' == charTyped) &&
         CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET &&
-        !editor.getSelectionModel().hasBlockSelection() && fileType != FileTypes.PLAIN_TEXT) {
+        !editor.getSelectionModel().hasBlockSelection() && editor.getCaretModel().getCaretCount() == 1 && fileType != FileTypes.PLAIN_TEXT) {
       handleAfterLParen(editor, fileType, charTyped);
     }
     else if ('}' == charTyped) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/BaseIndentEnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/BaseIndentEnterHandler.java
index 48c1dfb..524a2b2 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/BaseIndentEnterHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/BaseIndentEnterHandler.java
@@ -83,15 +83,7 @@
     myWorksWithFormatter = worksWithFormatter;
   }
 
-  @Override
-  public Result preprocessEnter(
-    @NotNull final PsiFile file,
-    @NotNull final Editor editor,
-    @NotNull final Ref<Integer> caretOffset,
-    @NotNull final Ref<Integer> caretAdvance,
-    @NotNull final DataContext dataContext,
-    final EditorActionHandler originalHandler)
-  {
+  protected Result shouldSkipWithResult(@NotNull final PsiFile file, @NotNull final Editor editor, @NotNull final DataContext dataContext) {
     final Project project = CommonDataKeys.PROJECT.getData(dataContext);
     if (project == null) {
       return Result.Continue;
@@ -119,7 +111,25 @@
     if (caret <= 0) {
       return Result.Continue;
     }
+    return null;
+  }
 
+  @Override
+  public Result preprocessEnter(
+    @NotNull final PsiFile file,
+    @NotNull final Editor editor,
+    @NotNull final Ref<Integer> caretOffset,
+    @NotNull final Ref<Integer> caretAdvance,
+    @NotNull final DataContext dataContext,
+    final EditorActionHandler originalHandler)
+  {
+    Result res = shouldSkipWithResult(file, editor, dataContext);
+    if (res != null) {
+      return res;
+    }
+
+    final Document document = editor.getDocument();
+    int caret = editor.getCaretModel().getOffset();
     final int lineNumber = document.getLineNumber(caret);
 
     final int lineStartOffset = document.getLineStartOffset(lineNumber);
@@ -207,7 +217,7 @@
   }
 
   @Nullable
-  private IElementType getNonWhitespaceElementType(final HighlighterIterator iterator, int currentLineStartOffset, final int prevLineStartOffset) {
+  protected IElementType getNonWhitespaceElementType(final HighlighterIterator iterator, int currentLineStartOffset, final int prevLineStartOffset) {
     while (!iterator.atEnd() && iterator.getEnd() >= currentLineStartOffset && iterator.getStart() >= prevLineStartOffset) {
       final IElementType tokenType = iterator.getTokenType();
       if (!myWhitespaceTokens.contains(tokenType)) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java
index 026564d..a965a85 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java
@@ -39,7 +39,6 @@
 import com.intellij.psi.PsiFile;
 import com.intellij.ui.LightweightHint;
 import com.intellij.util.containers.WeakList;
-import com.intellij.util.ui.UIUtil;
 import org.jdom.Element;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -184,7 +183,7 @@
 
   @Override
   public void releaseFoldings(@NotNull Editor editor) {
-    ApplicationManager.getApplication().assertIsDispatchThread();
+    ApplicationManagerEx.getApplicationEx().assertIsDispatchThread(editor.getComponent());
     final Project project = editor.getProject();
     if (project != null && (!project.equals(myProject) || !project.isOpen())) return;
 
@@ -217,32 +216,26 @@
 
     PsiDocumentManager.getInstance(myProject).commitDocument(document);
 
-    Runnable operation = new Runnable() {
+    Runnable runnable = updateFoldRegions(editor, true, true);
+    if (runnable != null) {
+      runnable.run();
+    }
+    if (myProject.isDisposed() || editor.isDisposed()) return;
+    foldingModel.runBatchFoldingOperation(new Runnable() {
       @Override
       public void run() {
-        Runnable runnable = updateFoldRegions(editor, true, true);
-        if (runnable != null) {
-          runnable.run();
+        DocumentFoldingInfo documentFoldingInfo = getDocumentFoldingInfo(document);
+        Editor[] editors = EditorFactory.getInstance().getEditors(document, myProject);
+        for (Editor otherEditor : editors) {
+          if (otherEditor == editor) continue;
+          documentFoldingInfo.loadFromEditor(otherEditor);
+          break;
         }
-        if (myProject.isDisposed() || editor.isDisposed()) return;
-        foldingModel.runBatchFoldingOperation(new Runnable() {
-          @Override
-          public void run() {
-            DocumentFoldingInfo documentFoldingInfo = getDocumentFoldingInfo(document);
-            Editor[] editors = EditorFactory.getInstance().getEditors(document, myProject);
-            for (Editor otherEditor : editors) {
-              if (otherEditor == editor) continue;
-              documentFoldingInfo.loadFromEditor(otherEditor);
-              break;
-            }
-            documentFoldingInfo.setToEditor(editor);
+        documentFoldingInfo.setToEditor(editor);
 
-            documentFoldingInfo.clear();
-          }
-        });
+        documentFoldingInfo.clear();
       }
-    };
-    UIUtil.invokeLaterIfNeeded(operation);
+    });
   }
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/DocumentFoldingInfo.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/DocumentFoldingInfo.java
index 0e420b0..9294f10 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/DocumentFoldingInfo.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/DocumentFoldingInfo.java
@@ -21,6 +21,7 @@
 import com.intellij.lang.folding.FoldingDescriptor;
 import com.intellij.lang.folding.LanguageFolding;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ex.ApplicationManagerEx;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
@@ -38,7 +39,6 @@
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.*;
 import java.util.*;
 
 class DocumentFoldingInfo implements JDOMExternalizable, CodeFoldingState {
@@ -64,7 +64,7 @@
   }
 
   void loadFromEditor(@NotNull Editor editor) {
-    assertDispatchThread();
+    assertDispatchThread(editor);
     LOG.assertTrue(!editor.isDisposed());
     clear();
 
@@ -95,12 +95,12 @@
     }
   }
 
-  private static void assertDispatchThread() {
-    assert SwingUtilities.isEventDispatchThread() : Thread.currentThread();
+  private static void assertDispatchThread(@NotNull Editor editor) {
+    ApplicationManagerEx.getApplicationEx().assertIsDispatchThread(editor.getComponent());
   }
 
   void setToEditor(@NotNull final Editor editor) {
-    assertDispatchThread();
+    assertDispatchThread(editor);
     final PsiManager psiManager = PsiManager.getInstance(myProject);
     if (psiManager.isDisposed()) return;
 
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlighter.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlighter.java
index 5976104..52b955e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlighter.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlighter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -42,7 +42,7 @@
   public void runActivity(@NotNull final Project project) {
     final EditorEventMulticaster eventMulticaster = EditorFactory.getInstance().getEventMulticaster();
 
-    CaretListener myCaretListener = new CaretListener() {
+    CaretListener myCaretListener = new CaretAdapter() {
       @Override
       public void caretPositionChanged(CaretEvent e) {
         myAlarm.cancelAllRequests();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java
index 77944cf..237d551 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java
@@ -251,19 +251,24 @@
 
       int lineOffset = 0;
 
+      boolean hasHighlighting = highlightStartOffset >= 0 && highlightEndOffset > highlightStartOffset;
+      TextRange highlightingRange = hasHighlighting ? new TextRange(highlightStartOffset, highlightEndOffset) : null;
+
       for (int i = 0; i < lines.length; i++) {
-        String line = escapeString(lines[i]);
+        String line = lines[i];
 
         myOneLineComponents[i] = new OneLineComponent();
 
-        TextRange range = null;
-        if (highlightStartOffset >= 0 && highlightEndOffset > lineOffset && highlightStartOffset < lineOffset + line.length()) {
-          int startOffset = Math.max(highlightStartOffset - lineOffset, 0);
-          int endOffset = Math.min(highlightEndOffset - lineOffset, line.length());
-          range = TextRange.create(startOffset, endOffset);
-        }
+        TextRange lRange = new TextRange(lineOffset, lineOffset + line.length());
+        TextRange hr = highlightingRange == null ? null : lRange.intersection(highlightingRange);
+        hr = hr == null ? null : hr.shiftRight(-lineOffset);
 
-        buf.append(myOneLineComponents[i].setup(line, isDisabled, strikeout, background, range));
+        String before = escapeString(hr == null ? line : line.substring(0, hr.getStartOffset()));
+        String in = hr == null ? "" : escapeString(hr.substring(line));
+        String after = hr == null ? "" : escapeString(line.substring(hr.getEndOffset(), line.length()));
+
+        TextRange escapedHighlightingRange = in.isEmpty() ? null : TextRange.create(before.length(), before.length() + in.length());
+        buf.append(myOneLineComponents[i].setup(before + in + after, isDisabled, strikeout, background, escapedHighlightingRange));
 
         if (isDisabledBeforeHighlight) {
           if (highlightStartOffset < 0 || highlightEndOffset > lineOffset) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoController.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoController.java
index 5335628..73ad86b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoController.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoController.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.
@@ -25,10 +25,7 @@
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.RangeMarker;
 import com.intellij.openapi.editor.ScrollType;
-import com.intellij.openapi.editor.event.CaretEvent;
-import com.intellij.openapi.editor.event.CaretListener;
-import com.intellij.openapi.editor.event.DocumentAdapter;
-import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.editor.event.*;
 import com.intellij.openapi.editor.impl.EditorImpl;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Disposer;
@@ -177,7 +174,7 @@
     List<ParameterInfoController> allControllers = getAllControllers(myEditor);
     allControllers.add(this);
 
-    myEditorCaretListener = new CaretListener(){
+    myEditorCaretListener = new CaretAdapter(){
       @Override
       public void caretPositionChanged(CaretEvent e) {
         myAlarm.cancelAllRequests();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java
index 114d493..b503950 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java
@@ -117,10 +117,15 @@
     final String newFileName =
       StringUtil.notNullize(language.getDisplayName(), "Injected") + " Fragment " + "(" +
       origFile.getName() + ":" + shreds.get(0).getHost().getTextRange().getStartOffset() + ")" + "." + fileType.getDefaultExtension();
+
+    // preserve \r\n as it is done in MultiHostRegistrarImpl
     myNewFile = factory.createFileFromText(newFileName, language, text, true, true);
-    myNewVirtualFile = (LightVirtualFile)myNewFile.getVirtualFile();
+    myNewVirtualFile = ObjectUtils.assertNotNull((LightVirtualFile)myNewFile.getVirtualFile());
     myNewVirtualFile.setOriginalFile(origFile.getVirtualFile());
-    assert myNewVirtualFile != null;
+
+    assert myNewFile != null : "PSI file is null";
+    assert myNewFile.getTextLength() == myNewVirtualFile.getLength() : "PSI / Virtual file text mismatch";
+    myNewVirtualFile.setOriginalFile(origFile.getVirtualFile());
     // suppress possible errors as in injected mode
     myNewFile.putUserData(InjectedLanguageUtil.FRANKENSTEIN_INJECTION,
                           injectedFile.getUserData(InjectedLanguageUtil.FRANKENSTEIN_INJECTION));
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
index 26115d4..cecdce5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
@@ -868,7 +868,7 @@
       }
     }, this);
 
-    final CaretListener caretListener = new CaretListener() {
+    final CaretListener caretListener = new CaretAdapter() {
       @Override
       public void caretPositionChanged(CaretEvent e) {
         if (!myChangeGuard && !myFinishing) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java
index be95eed..9d8c679 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.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.
@@ -80,7 +80,7 @@
       if (!lookup.performGuardedChange(new Runnable() {
         @Override
         public void run() {
-          EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, String.valueOf(charTyped), true);
+          EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, String.valueOf(charTyped), true);
         }
       })) {
         return Result.STOP;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java
index 3e0e264..1ee91b8 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.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.
@@ -250,7 +250,7 @@
         EditorEventMulticaster eventMulticaster = editorFactory.getEventMulticaster();
         eventMulticaster.addEditorMouseListener(myEditorMouseAdapter, project);
         eventMulticaster.addEditorMouseMotionListener(myEditorMouseMotionListener, project);
-        eventMulticaster.addCaretListener(new CaretListener() {
+        eventMulticaster.addCaretListener(new CaretAdapter() {
           @Override
           public void caretPositionChanged(CaretEvent e) {
             if (myHint != null) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/IncrementalSearchHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/IncrementalSearchHandler.java
index 36e5d29..fc0aed0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/IncrementalSearchHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/IncrementalSearchHandler.java
@@ -170,7 +170,7 @@
     };
     document.addDocumentListener(documentListener[0]);
 
-    caretListener[0] = new CaretListener() {
+    caretListener[0] = new CaretAdapter() {
       @Override
       public void caretPositionChanged(CaretEvent e) {
         PerHintSearchData data = hint.getUserData(SEARCH_DATA_IN_HINT_KEY);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
index 72d6d05..d3f658c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
@@ -34,10 +34,7 @@
 import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.colors.EditorColors;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
-import com.intellij.openapi.editor.event.CaretEvent;
-import com.intellij.openapi.editor.event.DocumentAdapter;
-import com.intellij.openapi.editor.event.DocumentEvent;
-import com.intellij.openapi.editor.event.MultipleCaretListener;
+import com.intellij.openapi.editor.event.*;
 import com.intellij.openapi.editor.ex.DocumentEx;
 import com.intellij.openapi.editor.markup.HighlighterLayer;
 import com.intellij.openapi.editor.markup.HighlighterTargetArea;
@@ -86,7 +83,7 @@
   private boolean myDocumentChanged = false;
 
   @Nullable private CommandAdapter myCommandListener;
-  @Nullable private MultipleCaretListener myCaretListener;
+  @Nullable private CaretListener myCaretListener;
 
   private final List<TemplateEditingListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
   private DocumentAdapter myEditorDocumentListener;
@@ -146,7 +143,7 @@
       }
     };
 
-    myCaretListener = new MultipleCaretListener() {
+    myCaretListener = new CaretAdapter() {
       @Override
       public void caretAdded(CaretEvent e) {
         if (isMultiCaretMode()) {
@@ -160,9 +157,6 @@
           finishTemplateEditing(false);
         }
       }
-
-      @Override
-      public void caretPositionChanged(CaretEvent e) {}
     };
 
     if (myEditor != null) {
@@ -173,7 +167,7 @@
   }
 
   private boolean isMultiCaretMode() {
-    return myEditor != null && myEditor.getCaretModel().supportsMultipleCarets() && myEditor.getCaretModel().getAllCarets().size() > 1;
+    return myEditor != null && myEditor.getCaretModel().getCaretCount() > 1;
   }
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/execution/actions/StopProcessAction.java b/platform/lang-impl/src/com/intellij/execution/actions/StopProcessAction.java
index e38cac9..652ea08 100644
--- a/platform/lang-impl/src/com/intellij/execution/actions/StopProcessAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/actions/StopProcessAction.java
@@ -32,13 +32,17 @@
  */
 public class StopProcessAction extends DumbAwareAction implements AnAction.TransparentUpdate {
 
-  private final ProcessHandler myProcessHandler;
+  private ProcessHandler myProcessHandler;
 
-  public StopProcessAction(@NotNull String text, @Nullable String description, @NotNull ProcessHandler processHandler) {
+  public StopProcessAction(@NotNull String text, @Nullable String description, @Nullable ProcessHandler processHandler) {
     super(text, description, AllIcons.Actions.Suspend);
     myProcessHandler = processHandler;
   }
 
+  public void setProcessHandler(@Nullable ProcessHandler processHandler) {
+    myProcessHandler = processHandler;
+  }
+
   @Override
   public void update(final AnActionEvent e) {
     update(e.getPresentation(), getTemplatePresentation(), myProcessHandler);
@@ -72,7 +76,7 @@
     stopProcess(myProcessHandler);
   }
 
-  public static void stopProcess(@NotNull ProcessHandler processHandler) {
+  public static void stopProcess(@Nullable ProcessHandler processHandler) {
     if (processHandler instanceof KillableProcess && processHandler.isProcessTerminating()) {
       // process termination was requested, but it's still alive
       // in this case 'force quit' will be performed
@@ -80,11 +84,13 @@
       return;
     }
 
-    if (processHandler.detachIsDefault()) {
-      processHandler.detachProcess();
-    }
-    else {
-      processHandler.destroyProcess();
+    if (processHandler != null) {
+      if (processHandler.detachIsDefault()) {
+        processHandler.detachProcess();
+      }
+      else {
+        processHandler.destroyProcess();
+      }
     }
   }
 
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java
index 9f8900e..bcb78d8 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java
@@ -24,10 +24,12 @@
 import com.intellij.openapi.command.impl.UndoManagerImpl;
 import com.intellij.openapi.command.undo.DocumentReferenceManager;
 import com.intellij.openapi.command.undo.UndoManager;
+import com.intellij.openapi.editor.ex.DocumentEx;
 import com.intellij.openapi.editor.ex.EditorEx;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Conditions;
+import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -110,23 +112,39 @@
     myExecuteActionHandler.runExecuteAction(myConsole, myConsoleView);
   }
 
-  protected boolean isEnabled() {
+  public boolean isEnabled() {
     return myEnabledCondition.value(myConsole);
   }
 
+  public void execute(@Nullable TextRange range, @NotNull String text, @Nullable EditorEx editor) {
+    if (range == null) {
+      myConsole.doAddPromptToHistory();
+      DocumentEx document = myConsole.getHistoryViewer().getDocument();
+      document.insertString(document.getTextLength(), text);
+      if (!text.endsWith("\n")) {
+        document.insertString(document.getTextLength(), "\n");
+      }
+    }
+    else {
+      assert editor != null;
+      myConsole.addTextRangeToHistory(range, editor, myExecuteActionHandler.myPreserveMarkup);
+    }
+    myExecuteActionHandler.addToCommandHistoryAndExecute(myConsole, myConsoleView, text);
+  }
+
   static abstract class ConsoleExecuteActionHandler {
-    private final ConsoleHistoryModel myConsoleHistoryModel;
+    private final ConsoleHistoryModel myCommandHistoryModel;
 
     private boolean myAddToHistory = true;
     final boolean myPreserveMarkup;
 
     public ConsoleExecuteActionHandler(boolean preserveMarkup) {
-      myConsoleHistoryModel = new ConsoleHistoryModel();
+      myCommandHistoryModel = new ConsoleHistoryModel();
       myPreserveMarkup = preserveMarkup;
     }
 
     public ConsoleHistoryModel getConsoleHistoryModel() {
-      return myConsoleHistoryModel;
+      return myCommandHistoryModel;
     }
 
     public boolean isEmptyCommandExecutionAllowed() {
@@ -139,10 +157,12 @@
 
     final void runExecuteAction(@NotNull LanguageConsoleImpl console, @Nullable LanguageConsoleView consoleView) {
       String text = console.prepareExecuteAction(myAddToHistory, myPreserveMarkup, true);
-
       ((UndoManagerImpl)UndoManager.getInstance(console.getProject())).invalidateActionsFor(DocumentReferenceManager.getInstance().create(console.getCurrentEditor().getDocument()));
+      addToCommandHistoryAndExecute(console, consoleView, text);
+    }
 
-      myConsoleHistoryModel.addToHistory(text);
+    private void addToCommandHistoryAndExecute(@NotNull LanguageConsoleImpl console, @Nullable LanguageConsoleView consoleView, @NotNull String text) {
+      myCommandHistoryModel.addToHistory(text);
       doExecute(text, console, consoleView);
     }
 
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java
index f7a1d6c..e9881c3 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java
@@ -3,8 +3,6 @@
 import com.intellij.codeInsight.hint.TooltipController;
 import com.intellij.codeInsight.hint.TooltipGroup;
 import com.intellij.ide.ui.UISettings;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.impl.ApplicationImpl;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.VisualPosition;
 import com.intellij.openapi.editor.colors.EditorFontType;
@@ -29,27 +27,38 @@
 
   private final EditorImpl editor;
 
-  private int maxAnnotationWidth = 0;
+  private int maxContentWidth;
   private int myLastPreferredHeight = -1;
-  private final int lineEndInset;
+  private final int gap;
 
   private final GutterContentProvider gutterContentProvider;
 
   private int lastGutterToolTipLine = -1;
 
-  public ConsoleGutterComponent(@NotNull Editor editor, @NotNull GutterContentProvider provider) {
+  private final boolean atLineStart;
+
+  public ConsoleGutterComponent(@NotNull Editor editor, @NotNull GutterContentProvider gutterContentProvider, boolean atLineStart) {
     this.editor = (EditorImpl)editor;
-    gutterContentProvider = provider;
-    addListeners();
+    this.gutterContentProvider = gutterContentProvider;
+    this.atLineStart = atLineStart;
 
-    addMouseMotionListener(this);
+    if (atLineStart) {
+      setOpaque(gutterContentProvider.getLineStartGutterOverlap(editor) == 0);
+    }
+    else {
+      addListeners();
+      setOpaque(false);
+    }
 
-    setOpaque(true);
-
-    lineEndInset = EditorUtil.getSpaceWidth(Font.PLAIN, editor);
+    int spaceWidth = EditorUtil.getSpaceWidth(Font.PLAIN, editor);
+    // at line start: icon/one-char symbol + space
+    gap = atLineStart ? spaceWidth * GutterContentProvider.MAX_LINE_END_GUTTER_WIDTH_IN_CHAR : spaceWidth;
+    maxContentWidth = atLineStart ? gap : 0;
   }
 
   private void addListeners() {
+    addMouseMotionListener(this);
+
     addMouseListener(new MouseAdapter() {
       @Override
       public void mouseClicked(MouseEvent e) {
@@ -61,9 +70,9 @@
   }
 
   public void updateSize(int start, int end) {
-    int oldAnnotationsWidth = maxAnnotationWidth;
+    int oldAnnotationsWidth = maxContentWidth;
     computeMaxAnnotationWidth(start, end);
-    if (oldAnnotationsWidth != maxAnnotationWidth || myLastPreferredHeight != editor.getPreferredHeight()) {
+    if (oldAnnotationsWidth != maxContentWidth || myLastPreferredHeight != editor.getPreferredHeight()) {
       processComponentEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED));
     }
     repaint();
@@ -72,8 +81,13 @@
   private void computeMaxAnnotationWidth(int start, int end) {
     gutterContentProvider.beforeUiComponentUpdate(editor);
 
+    if (atLineStart) {
+      return;
+    }
+
     if (!gutterContentProvider.hasText()) {
-      maxAnnotationWidth = 0;
+      editor.getSettings().setAdditionalColumnsCount(1);
+      maxContentWidth = 0;
       return;
     }
 
@@ -87,46 +101,51 @@
       }
     }
 
+    // line start gutter always has gap
     if (gutterSize != 0) {
-      gutterSize += lineEndInset;
+      gutterSize += gap;
     }
-    maxAnnotationWidth = Math.max(gutterSize, maxAnnotationWidth);
+    maxContentWidth = Math.max(gutterSize, maxContentWidth);
 
-    editor.getSettings().setAdditionalColumnsCount(1 + (maxAnnotationWidth / EditorUtil.getSpaceWidth(Font.PLAIN, editor)));
+    editor.getSettings().setAdditionalColumnsCount(1 + (maxContentWidth / EditorUtil.getSpaceWidth(Font.PLAIN, editor)));
   }
 
   @Override
   public Dimension getPreferredSize() {
     myLastPreferredHeight = editor.getPreferredHeight();
-    return new Dimension(maxAnnotationWidth, myLastPreferredHeight);
+    return new Dimension(maxContentWidth, myLastPreferredHeight);
   }
 
   @Override
   public void paint(Graphics g) {
-    ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart();
-    try {
-      Rectangle clip = g.getClipBounds();
-      if (clip.height < 0 || maxAnnotationWidth == 0) {
+    Rectangle clip = g.getClipBounds();
+    if (clip.height <= 0 || maxContentWidth == 0) {
+      return;
+    }
+
+    if (atLineStart) {
+      // don't paint in the overlapped region
+      if (clip.x >= maxContentWidth) {
         return;
       }
 
-      UISettings.setupAntialiasing(g);
+      g.setColor(editor.getBackgroundColor());
+      g.fillRect(clip.x, clip.y, Math.min(clip.width, maxContentWidth - clip.x), clip.height);
+    }
 
-      Graphics2D g2 = (Graphics2D)g;
-      Object hint = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
-      if (!UIUtil.isRetina()) {
-        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
-      }
+    UISettings.setupAntialiasing(g);
 
-      try {
-        paintAnnotations(g, clip);
-      }
-      finally {
-        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, hint);
-      }
+    Graphics2D g2 = (Graphics2D)g;
+    Object hint = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
+    if (!UIUtil.isRetina()) {
+      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
+    }
+
+    try {
+      paintAnnotations(g, clip);
     }
     finally {
-      ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintFinish();
+      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, hint);
     }
   }
 
@@ -138,17 +157,24 @@
       return;
     }
 
-    gutterContentProvider.beforeUiComponentUpdate(editor);
-
-    g.setColor(JBColor.BLUE);
+    if (!atLineStart) {
+      g.setColor(JBColor.BLUE);
+    }
     g.setFont(editor.getColorsScheme().getFont(EditorFontType.PLAIN));
+
     int y = ((startLine + 1) * lineHeight) - editor.getDescent();
     FontMetrics fontMetrics = editor.getFontMetrics(Font.PLAIN);
-    for (int i = startLine; i < endLine; i++) {
-      String text = gutterContentProvider.getText(editor.visualToLogicalPosition(new VisualPosition(i, 0)).line, editor);
-      if (text != null) {
-        // right-aligned
-        g.drawString(text, maxAnnotationWidth - lineEndInset - fontMetrics.stringWidth(text), y);
+    for (int line = startLine; line < endLine; line++) {
+      int logicalLine = editor.visualToLogicalPosition(new VisualPosition(line, 0)).line;
+      if (atLineStart) {
+        gutterContentProvider.drawIcon(logicalLine, g, y, editor);
+      }
+      else {
+        String text = gutterContentProvider.getText(logicalLine, editor);
+        if (text != null) {
+          // right-aligned
+          g.drawString(text, maxContentWidth - gap - fontMetrics.stringWidth(text), y);
+        }
       }
       y += lineHeight;
     }
@@ -190,6 +216,8 @@
   }
 
   public void documentCleared() {
-    maxAnnotationWidth = 0;
+    if (!atLineStart) {
+      maxContentWidth = 0;
+    }
   }
 }
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleIconGutterComponent.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleIconGutterComponent.java
deleted file mode 100644
index ec57b21..0000000
--- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleIconGutterComponent.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package com.intellij.execution.console;
-
-import com.intellij.ide.ui.UISettings;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.impl.ApplicationImpl;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.VisualPosition;
-import com.intellij.openapi.editor.colors.EditorFontType;
-import com.intellij.openapi.editor.ex.util.EditorUtil;
-import com.intellij.openapi.editor.impl.EditorImpl;
-import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ComponentEvent;
-
-class ConsoleIconGutterComponent extends JComponent {
-  private final int iconAreaWidth;
-
-  private int myLastPreferredHeight = -1;
-  private final EditorImpl editor;
-
-  private final GutterContentProvider gutterContentProvider;
-
-  public ConsoleIconGutterComponent(@NotNull Editor editor, @NotNull GutterContentProvider provider) {
-    this.editor = (EditorImpl)editor;
-    gutterContentProvider = provider;
-
-    // icon/one-char symbol + space
-    iconAreaWidth = EditorUtil.getSpaceWidth(Font.PLAIN, editor) * 2;
-  }
-
-  public void updateSize() {
-    if (myLastPreferredHeight != editor.getPreferredHeight()) {
-      fireResized();
-    }
-    repaint();
-  }
-
-  private void fireResized() {
-    processComponentEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED));
-  }
-
-  @Override
-  public Dimension getPreferredSize() {
-    myLastPreferredHeight = editor.getPreferredHeight();
-    return new Dimension(iconAreaWidth, myLastPreferredHeight);
-  }
-
-  @Override
-  public void paint(Graphics g) {
-    ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart();
-    try {
-      Rectangle clip = g.getClipBounds();
-      if (clip.height < 0) {
-        return;
-      }
-
-      g.setColor(editor.getBackgroundColor());
-      g.fillRect(clip.x, clip.y, clip.width, clip.height);
-
-      UISettings.setupAntialiasing(g);
-
-      Graphics2D g2 = (Graphics2D)g;
-      Object hint = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
-      if (!UIUtil.isRetina()) {
-        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
-      }
-
-      try {
-        paintAnnotations(g, clip);
-      }
-      finally {
-        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, hint);
-      }
-    }
-    finally {
-      ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintFinish();
-    }
-  }
-
-  private void paintAnnotations(Graphics g, Rectangle clip) {
-    int lineHeight = editor.getLineHeight();
-    int startLine = clip.y / lineHeight;
-    int endLine = Math.min(((clip.y + clip.height) / lineHeight) + 1, editor.getVisibleLineCount());
-    if (startLine >= endLine) {
-      return;
-    }
-
-    g.setFont(editor.getColorsScheme().getFont(EditorFontType.PLAIN));
-    int y = ((startLine + 1) * lineHeight) - editor.getDescent();
-    for (int i = startLine; i < endLine; i++) {
-      gutterContentProvider.drawIcon(editor.visualToLogicalPosition(new VisualPosition(i, 0)).line, g, y, editor);
-      y += lineHeight;
-    }
-  }
-}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java b/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java
index c283b1a..c2eed1a 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java
@@ -7,6 +7,8 @@
 import java.awt.*;
 
 public abstract class GutterContentProvider {
+  protected static final int MAX_LINE_END_GUTTER_WIDTH_IN_CHAR = 2;
+
   public void beforeUiComponentUpdate(@NotNull Editor editor) {
   }
 
@@ -31,4 +33,8 @@
   public boolean isShowSeparatorLine(int line, @NotNull Editor editor) {
     return true;
   }
+
+  public int getLineStartGutterOverlap(@NotNull Editor editor) {
+    return 0;
+  }
 }
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java
index 0d013fb..22b82c8 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java
@@ -147,7 +147,7 @@
   }
 
   public LanguageConsoleView build(@NotNull Project project, @NotNull Language language) {
-    GutteredLanguageConsole console = new GutteredLanguageConsole(project, language, gutterContentProvider, psiFileFactory);
+    GutteredLanguageConsole console = new GutteredLanguageConsole(language.getDisplayName() + " Console", project, language, gutterContentProvider, psiFileFactory);
     LanguageConsoleViewImpl consoleView = new LanguageConsoleViewImpl(console, true);
     if (executeActionHandler != null) {
       assert historyType != null;
@@ -184,11 +184,12 @@
     @Nullable
     private final PairFunction<VirtualFile, Project, PsiFile> psiFileFactory;
 
-    public GutteredLanguageConsole(@NotNull Project project,
+    public GutteredLanguageConsole(@NotNull String title,
+                                   @NotNull Project project,
                                    @NotNull Language language,
                                    @Nullable GutterContentProvider gutterContentProvider,
                                    @Nullable PairFunction<VirtualFile, Project, PsiFile> psiFileFactory) {
-      super(project, language.getDisplayName() + " Console", language, false);
+      super(project, title, new LightVirtualFile(title, language, ""), false, psiFileFactory);
 
       setShowSeparatorLine(false);
 
@@ -201,6 +202,11 @@
       return gutterContentProvider == null;
     }
 
+    @Override
+    int getMinHistoryLineCount() {
+      return 1;
+    }
+
     @NotNull
     @Override
     protected PsiFile createFile(@NotNull LightVirtualFile virtualFile, @NotNull Document document, @NotNull Project project) {
@@ -224,8 +230,8 @@
         return;
       }
 
-      final ConsoleIconGutterComponent lineStartGutter = new ConsoleIconGutterComponent(editor, gutterContentProvider);
-      final ConsoleGutterComponent lineEndGutter = new ConsoleGutterComponent(editor, gutterContentProvider);
+      final ConsoleGutterComponent lineStartGutter = new ConsoleGutterComponent(editor, gutterContentProvider, true);
+      final ConsoleGutterComponent lineEndGutter = new ConsoleGutterComponent(editor, gutterContentProvider, false);
       JLayeredPane layeredPane = new JBLayeredPane() {
         @Override
         public Dimension getPreferredSize() {
@@ -245,7 +251,7 @@
           int w = getWidth();
           int h = getHeight();
           int lineStartGutterWidth = lineStartGutter.getPreferredSize().width;
-          lineStartGutter.setBounds(0, 0, lineStartGutterWidth, h);
+          lineStartGutter.setBounds(0, 0, lineStartGutterWidth + gutterContentProvider.getLineStartGutterOverlap(editor.getEditor()), h);
 
           editor.setBounds(lineStartGutterWidth, 0, w - lineStartGutterWidth, h);
 
@@ -265,7 +271,7 @@
         }
       };
 
-      layeredPane.add(lineStartGutter, JLayeredPane.DEFAULT_LAYER);
+      layeredPane.add(lineStartGutter, JLayeredPane.PALETTE_LAYER);
 
       JScrollPane scrollPane = editor.getScrollPane();
       layeredPane.add(scrollPane.getViewport().getView(), JLayeredPane.DEFAULT_LAYER);
@@ -290,13 +296,13 @@
     }
 
     private final class GutterUpdateScheduler extends DocumentAdapter implements DocumentBulkUpdateListener {
-      private final ConsoleIconGutterComponent lineStartGutter;
+      private final ConsoleGutterComponent lineStartGutter;
       private final ConsoleGutterComponent lineEndGutter;
 
       private Task gutterSizeUpdater;
       private RangeHighlighterEx lineSeparatorPainter;
 
-      public GutterUpdateScheduler(@NotNull ConsoleIconGutterComponent lineStartGutter, @NotNull ConsoleGutterComponent lineEndGutter) {
+      public GutterUpdateScheduler(@NotNull ConsoleGutterComponent lineStartGutter, @NotNull ConsoleGutterComponent lineEndGutter) {
         this.lineStartGutter = lineStartGutter;
         this.lineEndGutter = lineEndGutter;
 
@@ -393,7 +399,7 @@
         @Override
         public void run() {
           if (!getHistoryViewer().isDisposed()) {
-            lineStartGutter.updateSize();
+            lineStartGutter.updateSize(start, end);
             lineEndGutter.updateSize(start, end);
           }
           gutterSizeUpdater = null;
diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
index da38faf..5b88d7c 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.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.
@@ -58,10 +58,7 @@
 import com.intellij.testFramework.LightVirtualFile;
 import com.intellij.ui.JBColor;
 import com.intellij.ui.SideBorder;
-import com.intellij.util.DocumentUtil;
-import com.intellij.util.FileContentUtil;
-import com.intellij.util.ObjectUtils;
-import com.intellij.util.SingleAlarm;
+import com.intellij.util.*;
 import com.intellij.util.ui.AbstractLayoutManager;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
@@ -124,6 +121,14 @@
   }
 
   public LanguageConsoleImpl(@NotNull Project project, @NotNull String title, @NotNull LightVirtualFile lightFile, boolean initComponents) {
+    this(project, title, lightFile, initComponents, null);
+  }
+
+  LanguageConsoleImpl(@NotNull Project project,
+                      @NotNull String title,
+                      @NotNull LightVirtualFile lightFile,
+                      boolean initComponents,
+                      @Nullable PairFunction<VirtualFile, Project, PsiFile> psiFileFactory) {
     myProject = project;
     myTitle = title;
     myVirtualFile = lightFile;
@@ -131,7 +136,7 @@
     myHistoryFile = new LightVirtualFile(getTitle() + ".history.txt", FileTypes.PLAIN_TEXT, "");
     myEditorDocument = FileDocumentManager.getInstance().getDocument(lightFile);
     assert myEditorDocument != null;
-    myFile = createFile(myVirtualFile, myEditorDocument, myProject);
+    myFile = psiFileFactory == null ? createFile(myVirtualFile, myEditorDocument, myProject) : psiFileFactory.fun(myVirtualFile, myProject);
     myConsoleEditor = (EditorEx)editorFactory.createEditor(myEditorDocument, myProject);
     myConsoleEditor.addFocusListener(myFocusListener);
     myCurrentEditor = myConsoleEditor;
@@ -173,7 +178,7 @@
     myHistoryViewer.getComponent().addComponentListener(new ComponentAdapter() {
       @Override
       public void componentResized(ComponentEvent e) {
-        if (myForceScrollToEnd.getAndSet(false)) {
+        if (myForceScrollToEnd.compareAndSet(true, false)) {
           scrollHistoryToEnd();
         }
       }
@@ -333,6 +338,8 @@
   }
 
   private void setPromptInner(@Nullable final String prompt) {
+    myUpdateQueue.checkDisposed();
+
     UIUtil.invokeAndWaitIfNeeded(new Runnable() {
       @Override
       public void run() {
@@ -472,20 +479,17 @@
   public boolean shouldScrollHistoryToEnd() {
     final Rectangle visibleArea = myHistoryViewer.getScrollingModel().getVisibleArea();
     final Dimension contentSize = myHistoryViewer.getContentSize();
-    return contentSize.getHeight() - visibleArea.getMaxY() < 2 * myHistoryViewer.getLineHeight();
+    return contentSize.getHeight() - visibleArea.getMaxY() < (getMinHistoryLineCount() * myHistoryViewer.getLineHeight());
   }
 
   private void scrollHistoryToEnd() {
-    final int lineCount = myHistoryViewer.getDocument().getLineCount();
-    if (lineCount == 0) {
-      return;
+    if (myHistoryViewer.getDocument().getTextLength() != 0) {
+      EditorUtil.scrollToTheEnd(myHistoryViewer);
     }
-    myHistoryViewer.getCaretModel().moveToOffset(myHistoryViewer.getDocument().getLineStartOffset(lineCount - 1), false);
-    myHistoryViewer.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
   }
 
   @NotNull
-  protected String addTextRangeToHistory(@NotNull TextRange textRange, @NotNull EditorEx consoleEditor, boolean preserveMarkup) {
+  protected String addTextRangeToHistory(@NotNull TextRange textRange, @NotNull EditorEx inputEditor, boolean preserveMarkup) {
     doAddPromptToHistory();
 
     final Document history = myHistoryViewer.getDocument();
@@ -493,16 +497,16 @@
     final int localStartOffset = textRange.getStartOffset();
     String text;
     EditorHighlighter highlighter;
-    if (consoleEditor instanceof EditorWindow) {
-      PsiFile file = ((EditorWindow)consoleEditor).getInjectedFile();
+    if (inputEditor instanceof EditorWindow) {
+      PsiFile file = ((EditorWindow)inputEditor).getInjectedFile();
       highlighter = HighlighterFactory.createHighlighter(file.getVirtualFile(), EditorColorsManager.getInstance().getGlobalScheme(), getProject());
       String fullText = InjectedLanguageUtil.getUnescapedText(file, null, null);
       highlighter.setText(fullText);
       text = textRange.substring(fullText);
     }
     else {
-      text = consoleEditor.getDocument().getText(textRange);
-      highlighter = consoleEditor.getHighlighter();
+      text = inputEditor.getDocument().getText(textRange);
+      highlighter = inputEditor.getHighlighter();
     }
     //offset can be changed after text trimming after insert due to buffer constraints
     int offset = appendToHistoryDocument(history, text);
@@ -524,9 +528,9 @@
       iterator.advance();
     }
     if (preserveMarkup) {
-      duplicateHighlighters(markupModel, DocumentMarkupModel.forDocument(consoleEditor.getDocument(), myProject, true), offset, textRange);
+      duplicateHighlighters(markupModel, DocumentMarkupModel.forDocument(inputEditor.getDocument(), myProject, true), offset, textRange);
       // don't copy editor markup model, i.e. brace matcher, spell checker, etc.
-      // duplicateHighlighters(markupModel, consoleEditor.getMarkupModel(), offset, textRange);
+      // duplicateHighlighters(markupModel, inputEditor.getMarkupModel(), offset, textRange);
     }
     if (!text.endsWith("\n")) {
       appendToHistoryDocument(history, "\n");
@@ -623,7 +627,7 @@
             myCurrentEditor = editor;
           }
           EmptyAction.registerActionShortcuts(editor.getComponent(), myConsoleEditor.getComponent());
-          editor.getCaretModel().addCaretListener(new CaretListener() {
+          editor.getCaretModel().addCaretListener(new CaretAdapter() {
             @Override
             public void caretPositionChanged(CaretEvent e) {
               queueUiUpdate(false);
@@ -686,6 +690,10 @@
     return true;
   }
 
+  int getMinHistoryLineCount() {
+    return 2;
+  }
+
   private class MyLayout extends AbstractLayoutManager {
     @Override
     public Dimension preferredLayoutSize(final Container parent) {
@@ -700,8 +708,8 @@
       }
 
       final EditorEx history = myHistoryViewer;
-      final EditorEx editor = componentCount == 2 ? myConsoleEditor : null;
-      if (editor == null) {
+      final EditorEx input = componentCount == 2 ? myConsoleEditor : null;
+      if (input == null) {
         parent.getComponent(0).setBounds(parent.getBounds());
         return;
       }
@@ -711,44 +719,44 @@
         return;
       }
       final Dimension historySize = history.getContentSize();
-      final Dimension editorSize = editor.getContentSize();
-      final Dimension newEditorSize = new Dimension();
+      final Dimension inputSize = input.getContentSize();
 
+      int newInputHeight;
       // deal with width
-      final int width = Math.max(editorSize.width, historySize.width);
-      newEditorSize.width = width + editor.getScrollPane().getHorizontalScrollBar().getHeight();
+      final int width = Math.max(inputSize.width, historySize.width);
       if (isHistoryViewerForceAdditionalColumnsUsage()) {
         history.getSoftWrapModel().forceAdditionalColumnsUsage();
-        editor.getSettings().setAdditionalColumnsCount(2 + (width - editorSize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, editor));
+        input.getSettings().setAdditionalColumnsCount(2 + (width - inputSize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, input));
         history.getSettings().setAdditionalColumnsCount(2 + (width - historySize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, history));
       }
 
-      // deal with height
-      if (historySize.width == 0) {
+      // deal with height, WEB-11122 we cannot trust editor width — it could be 0 in case of soft wrap even if editor has text
+      if (history.getDocument().getLineCount() == 0) {
         historySize.height = 0;
       }
-      final int minHistorySize = historySize.height > 0 ? 2 * history.getLineHeight() + (myShowSeparatorLine ? SEPARATOR_THICKNESS : 0) : 0;
-      final int minEditorSize = editor.isViewer() ? 0 : editor.getLineHeight();
-      final int editorPreferred = editor.isViewer() ? 0 : Math.max(minEditorSize, editorSize.height);
-      final int historyPreferred = Math.max(minHistorySize, historySize.height);
-      if (panelSize.height < minEditorSize) {
-        newEditorSize.height = panelSize.height;
+
+      int minHistoryHeight = historySize.height > 0 ? (getMinHistoryLineCount() * history.getLineHeight() + (myShowSeparatorLine ? SEPARATOR_THICKNESS : 0)) : 0;
+      int minInputHeight = input.isViewer() ? 0 : input.getLineHeight();
+      final int inputPreferredHeight = input.isViewer() ? 0 : Math.max(minInputHeight, inputSize.height);
+      final int historyPreferredHeight = Math.max(minHistoryHeight, historySize.height);
+      if (panelSize.height < minInputHeight) {
+        newInputHeight = panelSize.height;
       }
-      else if (panelSize.height < editorPreferred) {
-        newEditorSize.height = panelSize.height - minHistorySize;
+      else if (panelSize.height < inputPreferredHeight) {
+        newInputHeight = panelSize.height - minHistoryHeight;
       }
-      else if (panelSize.height < editorPreferred + historyPreferred) {
-        newEditorSize.height = editorPreferred;
+      else if (panelSize.height < (inputPreferredHeight + historyPreferredHeight) || inputPreferredHeight == 0) {
+        newInputHeight = inputPreferredHeight;
       }
       else {
-        newEditorSize.height = editorPreferred == 0 ? 0 : panelSize.height - historyPreferred;
+        newInputHeight = panelSize.height - historyPreferredHeight;
       }
-      final Dimension newHistorySize = new Dimension(width, panelSize.height - newEditorSize.height);
 
+      int newHistoryHeight = panelSize.height - newInputHeight;
       // apply
-      editor.getComponent().setBounds(0, newHistorySize.height, panelSize.width, newEditorSize.height);
+      input.getComponent().setBounds(0, newHistoryHeight, panelSize.width, newInputHeight);
       myForceScrollToEnd.compareAndSet(false, shouldScrollHistoryToEnd());
-      history.getComponent().setBounds(0, 0, panelSize.width, newHistorySize.height);
+      history.getComponent().setBounds(0, 0, panelSize.width, newHistoryHeight);
     }
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
index f729219..1c19e69 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
@@ -386,17 +386,22 @@
   }
 
   public void requestScrollingToEnd() {
-    if (myEditor == null || myFlushAlarm.isDisposed()) return;
-    final MyFlushRunnable scrollRunnable = new MyFlushRunnable() {
+    if (myEditor == null || myFlushAlarm.isDisposed()) {
+      return;
+    }
+
+    addFlushRequest(new MyFlushRunnable() {
       @Override
       public void doRun() {
         flushDeferredText();
-        if (myEditor == null || myFlushAlarm.isDisposed()) return;
+        if (myEditor == null || myFlushAlarm.isDisposed()) {
+          return;
+        }
+
         myEditor.getCaretModel().moveToOffset(myEditor.getDocument().getTextLength());
         myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
       }
-    };
-    addFlushRequest(scrollRunnable);
+    });
   }
 
   private void addFlushRequest(MyFlushRunnable scrollRunnable) {
@@ -480,13 +485,12 @@
           // 'Debugger' tab is active while 'Console' is not). It's also possible that newly added text contains long lines that
           // are soft wrapped. We want to update viewport position then when the console becomes visible.
           final Rectangle oldRectangle = e.getOldRectangle();
-          final Rectangle newRectangle = e.getNewRectangle();
           if (oldRectangle == null) {
             return;
           }
 
           Editor myEditor = e.getEditor();
-          if (oldRectangle.height <= 0 && newRectangle.height > 0 && myEditor.getSoftWrapModel().isSoftWrappingEnabled()
+          if (oldRectangle.height <= 0 && e.getNewRectangle().height > 0 && myEditor.getSoftWrapModel().isSoftWrappingEnabled()
               && myEditor.getCaretModel().getOffset() == myEditor.getDocument().getTextLength()) {
             EditorUtil.scrollToTheEnd(myEditor);
           }
@@ -834,19 +838,14 @@
     return ApplicationManager.getApplication().runReadAction(new Computable<EditorEx>() {
       @Override
       public EditorEx compute() {
-        final EditorEx editor = createRealEditor();
-
+        EditorEx editor = createRealEditor();
         editor.addEditorMouseListener(new EditorPopupHandler() {
           @Override
           public void invokePopup(final EditorMouseEvent event) {
             popupInvoked(event.getMouseEvent());
           }
         });
-        editor.getDocument().addDocumentListener(new DocumentListener() {
-          @Override
-          public void beforeDocumentChange(DocumentEvent event) {
-          }
-
+        editor.getDocument().addDocumentListener(new DocumentAdapter() {
           @Override
           public void documentChanged(DocumentEvent event) {
             onDocumentChanged(event);
diff --git a/platform/lang-impl/src/com/intellij/find/FindUtil.java b/platform/lang-impl/src/com/intellij/find/FindUtil.java
index e54074d..5c931bb 100644
--- a/platform/lang-impl/src/com/intellij/find/FindUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/FindUtil.java
@@ -34,6 +34,7 @@
 import com.intellij.openapi.editor.actions.IncrementalFindAction;
 import com.intellij.openapi.editor.colors.EditorColors;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.event.CaretAdapter;
 import com.intellij.openapi.editor.event.CaretEvent;
 import com.intellij.openapi.editor.event.CaretListener;
 import com.intellij.openapi.editor.ex.DocumentEx;
@@ -752,7 +753,7 @@
     return result;
   }
 
-  private static class MyListener implements CaretListener {
+  private static class MyListener extends CaretAdapter {
     private final Editor myEditor;
     private final RangeHighlighter mySegmentHighlighter;
 
@@ -818,7 +819,7 @@
           position = HintManager.ABOVE;
         }
       }
-      CaretListener listener = new CaretListener() {
+      CaretListener listener = new CaretAdapter() {
         @Override
         public void caretPositionChanged(CaretEvent e) {
           editor.putUserData(KEY, null);
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/TogglePreserveCaseAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/TogglePreserveCaseAction.java
index 1ceb624..755e232 100644
--- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/TogglePreserveCaseAction.java
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/TogglePreserveCaseAction.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.find.editorHeaderActions;
 
 import com.intellij.find.EditorSearchComponent;
@@ -5,7 +20,7 @@
 import com.intellij.openapi.actionSystem.AnActionEvent;
 
 public class TogglePreserveCaseAction extends EditorHeaderToggleAction  implements SecondaryHeaderAction {
-  private static final String TEXT = "Preser&ve Case";
+  private static final String TEXT = "&Preserve Case";
 
   public TogglePreserveCaseAction(EditorSearchComponent editorSearchComponent) {
     super(editorSearchComponent, TEXT);
diff --git a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
index 4c11fe2..7bc0e0c 100644
--- a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
+++ b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
@@ -127,7 +127,7 @@
                     return processor.process(usage);
                   }
                 };
-                FindInProjectUtil.findUsages(findModelCopy, psiDirectory, myProject, true, consumer, processPresentation);
+                FindInProjectUtil.findUsages(findModelCopy, psiDirectory, myProject, consumer, processPresentation);
               }
               finally {
                 myIsFindInProgress = false;
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
new file mode 100644
index 0000000..3650e18
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
@@ -0,0 +1,394 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.find.impl;
+
+import com.intellij.find.FindBundle;
+import com.intellij.find.FindModel;
+import com.intellij.find.ngrams.TrigramIndex;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.progress.EmptyProgressIndicator;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectCoreUtil;
+import com.intellij.openapi.roots.*;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.util.text.TrigramBuilder;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileFilter;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.cache.CacheManager;
+import com.intellij.psi.impl.cache.impl.id.IdIndex;
+import com.intellij.psi.impl.search.PsiSearchHelperImpl;
+import com.intellij.psi.search.*;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.usages.FindUsagesProcessPresentation;
+import com.intellij.usages.UsageLimitUtil;
+import com.intellij.usages.impl.UsageViewManagerImpl;
+import com.intellij.util.CommonProcessors;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.indexing.FileBasedIndexImpl;
+import gnu.trove.TIntHashSet;
+import gnu.trove.TIntIterator;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * @author peter
+ */
+class FindInProjectTask {
+  private static final int FILES_SIZE_LIMIT = 70 * 1024 * 1024; // megabytes.
+  private static final int SINGLE_FILE_SIZE_LIMIT = 5 * 1024 * 1024; // megabytes.
+  private final FindModel myFindModel;
+  private final Project myProject;
+  private final PsiManager myPsiManager;
+  @Nullable private final PsiDirectory myPsiDirectory;
+  private final FileIndex myFileIndex;
+  private final Condition<VirtualFile> myFileMask;
+  private final ProgressIndicator myProgress;
+  @Nullable private final Module myModule;
+  private final Set<PsiFile> myLargeFiles = ContainerUtil.newTroveSet();
+  private boolean myWarningShown;
+
+  FindInProjectTask(@NotNull final FindModel findModel,
+                    @NotNull final Project project,
+                    @Nullable final PsiDirectory psiDirectory) {
+    myFindModel = findModel;
+    myProject = project;
+    myPsiDirectory = psiDirectory;
+    myPsiManager = PsiManager.getInstance(project);
+
+    final String moduleName = findModel.getModuleName();
+    myModule = moduleName == null ? null : ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
+      @Override
+      public Module compute() {
+        return ModuleManager.getInstance(project).findModuleByName(moduleName);
+      }
+    });
+    myFileIndex = myModule == null ?
+                  ProjectRootManager.getInstance(project).getFileIndex() :
+                  ModuleRootManager.getInstance(myModule).getFileIndex();
+
+    final String filter = findModel.getFileFilter();
+    final Pattern pattern = FindInProjectUtil.createFileMaskRegExp(filter);
+
+    //noinspection unchecked
+    myFileMask = pattern == null ? Condition.TRUE : new Condition<VirtualFile>() {
+      @Override
+      public boolean value(VirtualFile file) {
+        return file != null && pattern.matcher(file.getName()).matches();
+      }
+    };
+
+    final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
+    myProgress = progress != null ? progress : new EmptyProgressIndicator();
+  }
+
+  public void findUsages(@NotNull final Processor<UsageInfo> consumer, @NotNull FindUsagesProcessPresentation processPresentation) {
+    try {
+      myProgress.setIndeterminate(true);
+      myProgress.setText("Scanning indexed files...");
+      final Set<PsiFile> filesForFastWordSearch = getFilesForFastWordSearch();
+      myProgress.setIndeterminate(false);
+
+      searchInFiles(consumer, processPresentation, filesForFastWordSearch);
+
+      myProgress.setIndeterminate(true);
+      myProgress.setText("Scanning non-indexed files...");
+      final Collection<PsiFile> otherFiles = collectFilesInScope(filesForFastWordSearch);
+      myProgress.setIndeterminate(false);
+
+      searchInFiles(consumer, processPresentation, otherFiles);
+    }
+    catch (ProcessCanceledException e) {
+      // fine
+    }
+
+    if (!myLargeFiles.isEmpty()) {
+      processPresentation.setLargeFilesWereNotScanned(myLargeFiles);
+    }
+
+    if (!myProgress.isCanceled()) {
+      myProgress.setText(FindBundle.message("find.progress.search.completed"));
+    }
+  }
+
+  private void searchInFiles(Processor<UsageInfo> consumer, FindUsagesProcessPresentation processPresentation, Collection<PsiFile> psiFiles) {
+    int i = 0;
+    long totalFilesSize = 0;
+    int count = 0;
+
+    for (final PsiFile psiFile : psiFiles) {
+      final VirtualFile virtualFile = psiFile.getVirtualFile();
+      final int index = i++;
+      if (virtualFile == null) continue;
+
+      long fileLength = UsageViewManagerImpl.getFileLength(virtualFile);
+      if (fileLength == -1) continue; // Binary or invalid
+
+      if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !Registry.is("find.search.in.project.files")) continue;
+
+      if (fileLength > SINGLE_FILE_SIZE_LIMIT) {
+        myLargeFiles.add(psiFile);
+        continue;
+      }
+
+      myProgress.checkCanceled();
+      myProgress.setFraction((double)index / psiFiles.size());
+      String text = FindBundle.message("find.searching.for.string.in.file.progress",
+                                       myFindModel.getStringToFind(), virtualFile.getPresentableUrl());
+      myProgress.setText(text);
+      myProgress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count));
+
+      int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, consumer);
+
+      count += countInFile;
+      if (countInFile > 0) {
+        totalFilesSize += fileLength;
+        if (totalFilesSize > FILES_SIZE_LIMIT && !myWarningShown) {
+          myWarningShown = true;
+          String message = FindBundle.message("find.excessive.total.size.prompt",
+                                              UsageViewManagerImpl.presentableSize(totalFilesSize),
+                                              ApplicationNamesInfo.getInstance().getProductName());
+          UsageLimitUtil.showAndCancelIfAborted(myProject, message, processPresentation.getUsageViewPresentation());
+        }
+      }
+    }
+  }
+
+  @NotNull
+  private Collection<PsiFile> collectFilesInScope(@NotNull final Set<PsiFile> alreadySearched) {
+    SearchScope customScope = myFindModel.getCustomScope();
+    final GlobalSearchScope globalCustomScope = toGlobal(customScope);
+
+    final boolean skipIndexed = canRelyOnIndices();
+
+    class EnumContentIterator implements ContentIterator {
+      final Set<PsiFile> myFiles = new LinkedHashSet<PsiFile>();
+
+      @Override
+      public boolean processFile(@NotNull final VirtualFile virtualFile) {
+        ApplicationManager.getApplication().runReadAction(new Runnable() {
+          public void run() {
+            ProgressManager.checkCanceled();
+            if (virtualFile.isDirectory() || !virtualFile.isValid() ||
+                !myFileMask.value(virtualFile) ||
+                (globalCustomScope != null && !globalCustomScope.contains(virtualFile))) {
+              return;
+            }
+
+            if (skipIndexed && isCoveredByIdIndex(virtualFile)) {
+              return;
+            }
+
+            PsiFile psiFile = myPsiManager.findFile(virtualFile);
+            if (psiFile != null && !(psiFile instanceof PsiBinaryFile) && !alreadySearched.contains(psiFile)) {
+              PsiFile sourceFile = (PsiFile)psiFile.getNavigationElement();
+              if (sourceFile != null) psiFile = sourceFile;
+              myFiles.add(psiFile);
+            }
+          }
+        });
+        return true;
+      }
+
+      @NotNull
+      private Collection<PsiFile> getFiles() {
+        return myFiles;
+      }
+    }
+
+    EnumContentIterator iterator = new EnumContentIterator();
+
+    if (customScope instanceof LocalSearchScope) {
+      for (VirtualFile file : getLocalScopeFiles((LocalSearchScope)customScope)) {
+        iterator.processFile(file);
+      }
+    }
+    else if (myPsiDirectory != null) {
+      myFileIndex.iterateContentUnderDirectory(myPsiDirectory.getVirtualFile(), iterator);
+    }
+    else {
+      boolean success = myFileIndex.iterateContent(iterator);
+      if (success && globalCustomScope != null && globalCustomScope.isSearchInLibraries()) {
+        final VirtualFile[] librarySources = ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile[]>() {
+          @Override
+          public VirtualFile[] compute() {
+            OrderEnumerator enumerator = myModule == null ? OrderEnumerator.orderEntries(myProject) : OrderEnumerator.orderEntries(myModule);
+            return enumerator.withoutModuleSourceEntries().withoutDepModules().getSourceRoots();
+          }
+        });
+        iterateAll(librarySources, globalCustomScope, iterator);
+      }
+    }
+    return iterator.getFiles();
+  }
+
+  private static boolean isCoveredByIdIndex(VirtualFile file) {
+    return IdIndex.isIndexable(FileBasedIndexImpl.getFileType(file)) &&
+           ((FileBasedIndexImpl)FileBasedIndex.getInstance()).isIndexingCandidate(file, IdIndex.NAME);
+  }
+
+  private static boolean iterateAll(@NotNull VirtualFile[] files, @NotNull final GlobalSearchScope searchScope, @NotNull final ContentIterator iterator) {
+    final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
+    final VirtualFileFilter contentFilter = new VirtualFileFilter() {
+      @Override
+      public boolean accept(@NotNull final VirtualFile file) {
+        return file.isDirectory() ||
+               !fileTypeManager.isFileIgnored(file) && !file.getFileType().isBinary() && searchScope.contains(file);
+      }
+    };
+    for (VirtualFile file : files) {
+      if (!VfsUtilCore.iterateChildrenRecursively(file, contentFilter, iterator)) return false;
+    }
+    return true;
+  }
+
+  @Nullable
+  private GlobalSearchScope toGlobal(@Nullable final SearchScope scope) {
+    if (scope instanceof GlobalSearchScope || scope == null) {
+      return (GlobalSearchScope)scope;
+    }
+    return ApplicationManager.getApplication().runReadAction(new Computable<GlobalSearchScope>() {
+      @Override
+      public GlobalSearchScope compute() {
+        return GlobalSearchScope.filesScope(myProject, getLocalScopeFiles((LocalSearchScope)scope));
+      }
+    });
+  }
+
+  @NotNull
+  private static Set<VirtualFile> getLocalScopeFiles(@NotNull LocalSearchScope scope) {
+    Set<VirtualFile> files = new LinkedHashSet<VirtualFile>();
+    for (PsiElement element : scope.getScope()) {
+      PsiFile file = element.getContainingFile();
+      if (file != null) {
+        ContainerUtil.addIfNotNull(files, file.getVirtualFile());
+      }
+    }
+    return files;
+  }
+
+  private boolean canRelyOnIndices() {
+    if (DumbService.isDumb(myProject)) return false;
+
+    if (myFindModel.isRegularExpressions()) return false;
+
+    // a local scope may be over a non-indexed file
+    if (myFindModel.getCustomScope() instanceof LocalSearchScope) return false;
+
+    String text = myFindModel.getStringToFind();
+    if (StringUtil.isEmptyOrSpaces(text)) return false;
+
+    if (TrigramIndex.ENABLED) return !TrigramBuilder.buildTrigram(text).isEmpty();
+
+    // $ is used to separate words when indexing plain-text files but not when indexing
+    // Java identifiers, so we can't consistently break a string containing $ characters into words
+
+    return myFindModel.isWholeWordsOnly() && text.indexOf('$') < 0;
+  }
+
+
+  @NotNull
+  private Set<PsiFile> getFilesForFastWordSearch() {
+    String stringToFind = myFindModel.getStringToFind();
+    if (stringToFind.isEmpty() || DumbService.getInstance(myProject).isDumb()) {
+      return Collections.emptySet();
+    }
+
+    SearchScope customScope = myFindModel.getCustomScope();
+    GlobalSearchScope scope = myPsiDirectory != null
+                              ? GlobalSearchScopesCore.directoryScope(myPsiDirectory, true)
+                              : myModule != null
+                                ? myModule.getModuleContentScope()
+                                : customScope instanceof GlobalSearchScope
+                                  ? (GlobalSearchScope)customScope
+                                  : toGlobal(customScope);
+    if (scope == null) {
+      scope = ProjectScope.getContentScope(myProject);
+    }
+
+    final Set<PsiFile> resultFiles = new LinkedHashSet<PsiFile>();
+
+    if (TrigramIndex.ENABLED) {
+      Set<Integer> keys = ContainerUtil.newTroveSet();
+      TIntHashSet trigrams = TrigramBuilder.buildTrigram(stringToFind);
+      TIntIterator it = trigrams.iterator();
+      while (it.hasNext()) {
+        keys.add(it.next());
+      }
+
+      if (!keys.isEmpty()) {
+        List<VirtualFile> hits = new ArrayList<VirtualFile>();
+        FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor<VirtualFile>(hits), scope);
+
+        for (VirtualFile hit : hits) {
+          if (myFileMask.value(hit)) {
+            resultFiles.add(findFile(hit));
+          }
+        }
+
+        return resultFiles;
+      }
+    }
+
+    PsiSearchHelperImpl helper = (PsiSearchHelperImpl)PsiSearchHelper.SERVICE.getInstance(myProject);
+    helper.processFilesWithText(scope, UsageSearchContext.ANY, myFindModel.isCaseSensitive(), stringToFind, new Processor<VirtualFile>() {
+      @Override
+      public boolean process(VirtualFile file) {
+        if (myFileMask.value(file)) {
+          ContainerUtil.addIfNotNull(resultFiles, findFile(file));
+        }
+        return true;
+      }
+    });
+
+    // in case our word splitting is incorrect
+    for (PsiFile file : CacheManager.SERVICE.getInstance(myProject)
+      .getFilesWithWord(stringToFind, UsageSearchContext.ANY, scope, myFindModel.isCaseSensitive())) {
+      if (myFileMask.value(file.getVirtualFile())) {
+        resultFiles.add(file);
+      }
+    }
+
+    return resultFiles;
+  }
+
+  private PsiFile findFile(@NotNull final VirtualFile virtualFile) {
+    return ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
+      @Override
+      public PsiFile compute() {
+        return myPsiManager.findFile(virtualFile);
+      }
+    });
+  }
+
+}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
index 2fefcc9..d788d9c 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
@@ -19,73 +19,54 @@
 import com.intellij.BundleBase;
 import com.intellij.find.*;
 import com.intellij.find.findInProject.FindInProjectManager;
-import com.intellij.find.ngrams.TrigramIndex;
 import com.intellij.icons.AllIcons;
 import com.intellij.ide.DataManager;
 import com.intellij.navigation.ItemPresentation;
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ApplicationNamesInfo;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileEditor.FileEditor;
-import com.intellij.openapi.fileTypes.FileTypeManager;
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
 import com.intellij.openapi.progress.ProcessCanceledException;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.progress.util.ProgressWrapper;
 import com.intellij.openapi.progress.util.TooManyUsagesStatus;
-import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.project.IndexNotReadyException;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectCoreUtil;
-import com.intellij.openapi.roots.*;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.Factory;
-import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.util.text.TrigramBuilder;
-import com.intellij.openapi.vfs.*;
+import com.intellij.openapi.vfs.LocalFileProvider;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
 import com.intellij.openapi.vfs.ex.VirtualFileManagerEx;
 import com.intellij.psi.*;
-import com.intellij.psi.impl.cache.CacheManager;
-import com.intellij.psi.impl.cache.impl.id.IdIndex;
-import com.intellij.psi.search.*;
+import com.intellij.psi.search.LocalSearchScope;
+import com.intellij.psi.search.SearchScope;
 import com.intellij.ui.content.Content;
 import com.intellij.usageView.UsageInfo;
 import com.intellij.usageView.UsageViewManager;
 import com.intellij.usages.ConfigurableUsageTarget;
 import com.intellij.usages.FindUsagesProcessPresentation;
-import com.intellij.usages.UsageLimitUtil;
 import com.intellij.usages.UsageViewPresentation;
-import com.intellij.usages.impl.UsageViewManagerImpl;
-import com.intellij.util.CommonProcessors;
 import com.intellij.util.Function;
 import com.intellij.util.PatternUtil;
 import com.intellij.util.Processor;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.indexing.FileBasedIndex;
-import com.intellij.util.indexing.FileBasedIndexImpl;
-import gnu.trove.THashSet;
-import gnu.trove.TIntHashSet;
-import gnu.trove.TIntIterator;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.io.File;
-import java.util.*;
+import java.util.List;
 import java.util.regex.Pattern;
 
 public class FindInProjectUtil {
   private static final int USAGES_PER_READ_ACTION = 100;
-  private static final int FILES_SIZE_LIMIT = 70 * 1024 * 1024; // megabytes.
-  private static final int SINGLE_FILE_SIZE_LIMIT = 5 * 1024 * 1024; // megabytes.
 
   private FindInProjectUtil() {}
 
@@ -156,34 +137,6 @@
     return virtualFile == null ? null : psiManager.findDirectory(virtualFile);
   }
 
-  private static void addFilesUnderDirectory(@NotNull PsiDirectory directory,
-                                             @NotNull Collection<PsiFile> fileList,
-                                             boolean isRecursive,
-                                             @Nullable Pattern fileMaskRegExp) {
-    final PsiElement[] children = directory.getChildren();
-
-    for (PsiElement child : children) {
-      if (child instanceof PsiFile &&
-          (fileMaskRegExp == null ||
-           fileMaskRegExp.matcher(((PsiFile)child).getName()).matches()
-          )
-        ) {
-        PsiFile file = (PsiFile)child;
-        PsiFile sourceFile = (PsiFile)file.getNavigationElement();
-        if (sourceFile != null) file = sourceFile;
-        fileList.add(file);
-      }
-      else if (isRecursive && child instanceof PsiDirectory) {
-        addFilesUnderDirectory((PsiDirectory)child, fileList, isRecursive, fileMaskRegExp);
-      }
-    }
-  }
-
-  @Nullable
-  private static Pattern createFileMaskRegExp(@NotNull FindModel findModel) {
-    final String filter = findModel.getFileFilter();
-    return createFileMaskRegExp(filter);
-  }
 
   @Nullable
   public static Pattern createFileMaskRegExp(@Nullable String filter) {
@@ -210,74 +163,12 @@
   public static void findUsages(@NotNull FindModel findModel,
                                 final PsiDirectory psiDirectory,
                                 @NotNull final Project project,
-                                boolean showWarnings,
                                 @NotNull final Processor<UsageInfo> consumer,
                                 @NotNull FindUsagesProcessPresentation processPresentation) {
-    final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
-
-    final Collection<PsiFile> psiFiles = getFilesToSearchIn(findModel, project, psiDirectory);
-    try {
-      final Set<PsiFile> largeFiles = new THashSet<PsiFile>();
-
-      int i = 0;
-      long totalFilesSize = 0;
-      int count = 0;
-      final boolean[] warningShown = {false};
-
-      for (final PsiFile psiFile : psiFiles) {
-        final VirtualFile virtualFile = psiFile.getVirtualFile();
-        final int index = i++;
-        if (virtualFile == null) continue;
-
-        long fileLength = UsageViewManagerImpl.getFileLength(virtualFile);
-        if (fileLength == -1) continue; // Binary or invalid
-
-        if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !Registry.is("find.search.in.project.files")) continue;
-
-        if (fileLength > SINGLE_FILE_SIZE_LIMIT) {
-          largeFiles.add(psiFile);
-          continue;
-        }
-
-        if (progress != null) {
-          progress.checkCanceled();
-          progress.setFraction((double)index / psiFiles.size());
-          String text = FindBundle.message("find.searching.for.string.in.file.progress",
-                                           findModel.getStringToFind(), virtualFile.getPresentableUrl());
-          progress.setText(text);
-          progress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count));
-        }
-
-        int countInFile = processUsagesInFile(psiFile, findModel, consumer);
-
-        count += countInFile;
-        if (countInFile > 0) {
-          totalFilesSize += fileLength;
-          if (totalFilesSize > FILES_SIZE_LIMIT && !warningShown[0]) {
-            warningShown[0] = true;
-            String message = FindBundle.message("find.excessive.total.size.prompt",
-                                                UsageViewManagerImpl.presentableSize(totalFilesSize),
-                                                ApplicationNamesInfo.getInstance().getProductName());
-            UsageLimitUtil.showAndCancelIfAborted(project, message, processPresentation.getUsageViewPresentation());
-          }
-        }
-      }
-
-
-      if (!largeFiles.isEmpty()) {
-        processPresentation.setLargeFilesWereNotScanned(largeFiles);
-      }
-    }
-    catch (ProcessCanceledException e) {
-      // fine
-    }
-
-    if (progress != null && !progress.isCanceled()) {
-      progress.setText(FindBundle.message("find.progress.search.completed"));
-    }
+    new FindInProjectTask(findModel, project, psiDirectory).findUsages(consumer, processPresentation);
   }
 
-  private static int processUsagesInFile(@NotNull final PsiFile psiFile,
+  static int processUsagesInFile(@NotNull final PsiFile psiFile,
                                          @NotNull final FindModel findModel,
                                          @NotNull final Processor<UsageInfo> consumer) {
     if (findModel.getStringToFind().isEmpty()) {
@@ -317,279 +208,6 @@
     return count;
   }
 
-  private static PsiFile findFile(@NotNull final PsiManager psiManager, @NotNull final VirtualFile virtualFile) {
-    return ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
-      @Override
-      public PsiFile compute() {
-        return psiManager.findFile(virtualFile);
-      }
-    });
-  }
-
-  @NotNull
-  private static Collection<PsiFile> getFilesToSearchIn(@NotNull final FindModel findModel,
-                                                        @NotNull final Project project,
-                                                        final PsiDirectory psiDirectory) {
-    final String moduleName = findModel.getModuleName();
-    final Module module = moduleName == null ? null : ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
-      @Override
-      public Module compute() {
-        return ModuleManager.getInstance(project).findModuleByName(moduleName);
-      }
-    });
-    final FileIndex fileIndex = module == null ?
-                                ProjectRootManager.getInstance(project).getFileIndex() :
-                                ModuleRootManager.getInstance(module).getFileIndex();
-
-    if (psiDirectory == null || findModel.isWithSubdirectories() && fileIndex.isInContent(psiDirectory.getVirtualFile())) {
-      final Pattern fileMaskRegExp = createFileMaskRegExp(findModel);
-      // optimization
-      Pair<Boolean, Collection<PsiFile>> fastWords = getFilesForFastWordSearch(findModel, project, psiDirectory, fileMaskRegExp, module, fileIndex);
-      final Collection<PsiFile> filesForFastWordSearch = fastWords.getSecond();
-
-      final boolean useIdIndex = fastWords.getFirst() && canOptimizeForFastWordSearch(findModel);
-
-      SearchScope customScope = findModel.getCustomScope();
-      final GlobalSearchScope globalCustomScope = toGlobal(project, customScope);
-
-      class EnumContentIterator implements ContentIterator {
-        final Set<PsiFile> myFiles = new LinkedHashSet<PsiFile>(filesForFastWordSearch);
-        final PsiManager psiManager = PsiManager.getInstance(project);
-
-        @Override
-        public boolean processFile(@NotNull VirtualFile virtualFile) {
-          ProgressManager.checkCanceled();
-          if (virtualFile.isDirectory() ||
-              (fileMaskRegExp != null && !fileMaskRegExp.matcher(virtualFile.getName()).matches()) ||
-              (globalCustomScope != null && !globalCustomScope.contains(virtualFile))) {
-            return true;
-          }
-          
-          if (useIdIndex && isCoveredByIdIndex(virtualFile)) {
-            return true;
-          }
-
-          PsiFile psiFile = findFile(psiManager, virtualFile);
-          if (psiFile != null && !(psiFile instanceof PsiBinaryFile)) {
-            myFiles.add(psiFile);
-          }
-          return true;
-        }
-
-        @NotNull
-        private Collection<PsiFile> getFiles() {
-          return myFiles;
-        }
-      }
-
-      EnumContentIterator iterator = new EnumContentIterator();
-
-      if (customScope instanceof LocalSearchScope) {
-        for (VirtualFile file : getLocalScopeFiles((LocalSearchScope)customScope)) {
-          iterator.processFile(file);
-        }
-      }
-
-      if (psiDirectory == null) {
-        boolean success = fileIndex.iterateContent(iterator);
-        if (success && globalCustomScope != null && globalCustomScope.isSearchInLibraries()) {
-          final VirtualFile[] librarySources = ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile[]>() {
-            @Override
-            public VirtualFile[] compute() {
-              OrderEnumerator enumerator = module == null ? OrderEnumerator.orderEntries(project) : OrderEnumerator.orderEntries(module);
-              return enumerator.withoutModuleSourceEntries().withoutDepModules().getSourceRoots();
-            }
-          });
-          iterateAll(librarySources, globalCustomScope, iterator);
-        }
-      }
-      else {
-        fileIndex.iterateContentUnderDirectory(psiDirectory.getVirtualFile(), iterator);
-      }
-      return iterator.getFiles();
-    }
-    if (psiDirectory.isValid()) {
-      final Collection<PsiFile> fileList = new THashSet<PsiFile>();
-      ApplicationManager.getApplication().runReadAction(new Runnable() {
-        @Override
-        public void run() {
-          addFilesUnderDirectory(psiDirectory, fileList, findModel.isWithSubdirectories(), createFileMaskRegExp(findModel));
-        }
-      });
-
-      return fileList;
-    }
-    return Collections.emptyList();
-  }
-
-  private static boolean isCoveredByIdIndex(VirtualFile file) {
-    return IdIndex.isIndexable(FileBasedIndexImpl.getFileType(file)) && 
-           ((FileBasedIndexImpl)FileBasedIndex.getInstance()).isIndexingCandidate(file, IdIndex.NAME);
-  }
-
-  private static boolean iterateAll(@NotNull VirtualFile[] files, @NotNull final GlobalSearchScope searchScope, @NotNull final ContentIterator iterator) {
-    final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
-    final VirtualFileFilter contentFilter = new VirtualFileFilter() {
-      @Override
-      public boolean accept(@NotNull final VirtualFile file) {
-        return file.isDirectory() ||
-               !fileTypeManager.isFileIgnored(file) && !file.getFileType().isBinary() && searchScope.contains(file);
-      }
-    };
-    for (VirtualFile file : files) {
-      if (!VfsUtilCore.iterateChildrenRecursively(file, contentFilter, iterator)) return false;
-    }
-    return true;
-  }
-
-  @Nullable
-  private static GlobalSearchScope toGlobal(@NotNull final Project project, @Nullable final SearchScope scope) {
-    if (scope instanceof GlobalSearchScope || scope == null) {
-      return (GlobalSearchScope)scope;
-    }
-    return ApplicationManager.getApplication().runReadAction(new Computable<GlobalSearchScope>() {
-      @Override
-      public GlobalSearchScope compute() {
-        return GlobalSearchScope.filesScope(project, getLocalScopeFiles((LocalSearchScope)scope));
-      }
-    });
-  }
-
-  @NotNull
-  private static Set<VirtualFile> getLocalScopeFiles(@NotNull LocalSearchScope scope) {
-    Set<VirtualFile> files = new LinkedHashSet<VirtualFile>();
-    for (PsiElement element : scope.getScope()) {
-      PsiFile file = element.getContainingFile();
-      if (file != null) {
-        ContainerUtil.addIfNotNull(files, file.getVirtualFile());
-      }
-    }
-    return files;
-  }
-
-  @NotNull
-  private static Pair<Boolean, Collection<PsiFile>> getFilesForFastWordSearch(@NotNull final FindModel findModel,
-                                                                              @NotNull final Project project,
-                                                                              @Nullable final PsiDirectory psiDirectory,
-                                                                              final Pattern fileMaskRegExp,
-                                                                              @Nullable final Module module,
-                                                                              @NotNull FileIndex fileIndex) {
-    if (DumbService.getInstance(project).isDumb()) {
-      return new Pair<Boolean, Collection<PsiFile>>(false, Collections.<PsiFile>emptyList());
-    }
-
-    final PsiManager pm = PsiManager.getInstance(project);
-    CacheManager cacheManager = CacheManager.SERVICE.getInstance(project);
-    SearchScope customScope = findModel.getCustomScope();
-    GlobalSearchScope scope = psiDirectory != null
-                              ? GlobalSearchScopesCore.directoryScope(psiDirectory, true)
-                              : module != null
-                                ? module.getModuleContentScope()
-                                : customScope instanceof GlobalSearchScope
-                                  ? (GlobalSearchScope)customScope
-                                  : toGlobal(project, customScope);
-    if (scope == null) {
-      scope = ProjectScope.getContentScope(project);
-    }
-
-    Set<Integer> keys = new THashSet<Integer>(30);
-    final Set<PsiFile> resultFiles = new THashSet<PsiFile>();
-    boolean fast = false;
-
-    String stringToFind = findModel.getStringToFind();
-    if (TrigramIndex.ENABLED) {
-      TIntHashSet trigrams = TrigramBuilder.buildTrigram(stringToFind);
-      TIntIterator it = trigrams.iterator();
-      while (it.hasNext()) {
-        keys.add(it.next());
-      }
-
-      if (!keys.isEmpty()) {
-        fast = true;
-        List<VirtualFile> hits = new ArrayList<VirtualFile>();
-        FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor<VirtualFile>(hits), scope);
-
-        for (VirtualFile hit : hits) {
-          resultFiles.add(findFile(pm, hit));
-        }
-
-        filterMaskedFiles(resultFiles, fileMaskRegExp);
-        if (resultFiles.isEmpty()) return new Pair<Boolean, Collection<PsiFile>>(true, resultFiles);
-      }
-    }
-
-
-    // $ is used to separate words when indexing plain-text files but not when indexing
-    // Java identifiers, so we can't consistently break a string containing $ characters into words
-
-    fast |= findModel.isWholeWordsOnly() && stringToFind.indexOf('$') < 0;
-
-    List<String> words = StringUtil.getWordsInStringLongestFirst(stringToFind);
-
-    for (int i = 0; i < words.size(); i++) {
-      String word = words.get(i);
-
-      PsiFile[] files = cacheManager.getFilesWithWord(word, UsageSearchContext.ANY, scope, findModel.isCaseSensitive());
-      if (files.length == 0) {
-        resultFiles.clear();
-        break;
-      }
-
-      final List<PsiFile> psiFiles = Arrays.asList(files);
-
-      if (i == 0 && keys.isEmpty()) {
-        resultFiles.addAll(psiFiles);
-      }
-      else {
-        resultFiles.retainAll(psiFiles);
-      }
-
-      filterMaskedFiles(resultFiles, fileMaskRegExp);
-      if (resultFiles.isEmpty()) break;
-    }
-
-    if (stringToFind.isEmpty()) {
-      fileIndex.iterateContent(new ContentIterator() {
-        @Override
-        public boolean processFile(VirtualFile file) {
-          if (!file.isDirectory() && fileMaskRegExp.matcher(file.getName()).matches()) {
-            PsiFile psiFile = findFile(pm, file);
-            if (psiFile != null) {
-              resultFiles.add(psiFile);
-            }
-          }
-          return true;
-        }
-      });
-    }
-    else {
-      // in case our word splitting is incorrect
-      PsiFile[] allWordsFiles =
-        cacheManager.getFilesWithWord(stringToFind, UsageSearchContext.ANY, scope, findModel.isCaseSensitive());
-      ContainerUtil.addAll(resultFiles, allWordsFiles);
-
-      filterMaskedFiles(resultFiles, fileMaskRegExp);
-    }
-
-    return new Pair<Boolean, Collection<PsiFile>>(fast, resultFiles);
-  }
-
-  private static void filterMaskedFiles(@NotNull final Set<PsiFile> resultFiles, @Nullable final Pattern fileMaskRegExp) {
-    if (fileMaskRegExp != null) {
-      for (Iterator<PsiFile> iterator = resultFiles.iterator(); iterator.hasNext();) {
-        PsiFile file = iterator.next();
-        if (!fileMaskRegExp.matcher(file.getName()).matches()) {
-          iterator.remove();
-        }
-      }
-    }
-  }
-
-  private static boolean canOptimizeForFastWordSearch(@NotNull final FindModel findModel) {
-    return !findModel.isRegularExpressions()
-           && (findModel.getCustomScope() == null || findModel.getCustomScope() instanceof GlobalSearchScope);
-  }
-
   private static int addToUsages(@NotNull Document document, @NotNull Processor<UsageInfo> consumer, @NotNull FindModel findModel,
                                  @NotNull final PsiFile psiFile, @NotNull int[] offsetRef, int maxUsages) {
     int count = 0;
diff --git a/platform/lang-impl/src/com/intellij/find/ngrams/TrigramIndex.java b/platform/lang-impl/src/com/intellij/find/ngrams/TrigramIndex.java
index 9fdc87e..6cf661d 100644
--- a/platform/lang-impl/src/com/intellij/find/ngrams/TrigramIndex.java
+++ b/platform/lang-impl/src/com/intellij/find/ngrams/TrigramIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -38,13 +38,13 @@
 
   private static final FileBasedIndex.InputFilter INPUT_FILTER = new FileBasedIndex.InputFilter() {
     @Override
-    public boolean acceptInput(VirtualFile file) {
+    public boolean acceptInput(@NotNull VirtualFile file) {
       return !file.getFileType().isBinary();
     }
   };
   private static final FileBasedIndex.InputFilter NO_FILES = new FileBasedIndex.InputFilter() {
     @Override
-    public boolean acceptInput(VirtualFile file) {
+    public boolean acceptInput(@NotNull VirtualFile file) {
       return false;
     }
   };
@@ -76,11 +76,13 @@
     };
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<Integer> getKeyDescriptor() {
     return EnumeratorIntegerDescriptor.INSTANCE;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     if (ENABLED) {
diff --git a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
index 86fe9de..7e220c1 100644
--- a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
+++ b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
@@ -569,7 +569,7 @@
             myIsFindInProgress = true;
 
             FindInProjectUtil.findUsages(myFindModelCopy, myPsiDirectory, myProject,
-                                         true, new AdapterProcessor<UsageInfo, Usage>(processor, UsageInfo2UsageAdapter.CONVERTER),
+                                         new AdapterProcessor<UsageInfo, Usage>(processor, UsageInfo2UsageAdapter.CONVERTER),
                                          myProcessPresentation);
           }
           finally {
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/DetectedFrameworksData.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/DetectedFrameworksData.java
index 0985d6b..dfd6c9c 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/DetectedFrameworksData.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/DetectedFrameworksData.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -141,7 +141,7 @@
 
   private static class TIntHashSetExternalizer implements DataExternalizer<TIntHashSet> {
     @Override
-    public void save(DataOutput out, TIntHashSet value) throws IOException {
+    public void save(@NotNull DataOutput out, TIntHashSet value) throws IOException {
       out.writeInt(value.size());
       final TIntIterator iterator = value.iterator();
       while (iterator.hasNext()) {
@@ -150,7 +150,7 @@
     }
 
     @Override
-    public TIntHashSet read(DataInput in) throws IOException {
+    public TIntHashSet read(@NotNull DataInput in) throws IOException {
       int size = in.readInt();
       final TIntHashSet set = new TIntHashSet(size);
       while (size-- > 0) {
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectionIndex.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectionIndex.java
index bc6eba2..514f077 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectionIndex.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectionIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -91,11 +91,13 @@
     };
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<Integer> getKeyDescriptor() {
     return EnumeratorIntegerDescriptor.INSTANCE;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     final Set<FileType> acceptedTypes = new HashSet<FileType>();
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SaveAsAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SaveAsAction.java
index 07eee55..410eb95 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SaveAsAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SaveAsAction.java
@@ -1,9 +1,9 @@
 package com.intellij.ide.actions;
 
+import com.intellij.ide.util.PlatformPackageUtil;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -28,6 +28,6 @@
     final VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(dataContext);
     @SuppressWarnings({"ConstantConditions"}) final PsiElement element = PsiManager.getInstance(project).findFile(virtualFile);
     if(element==null) return;
-    CopyHandler.doCopy(new PsiElement[] {element.getContainingFile()}, element.getContainingFile().getContainingDirectory());
+    CopyHandler.doCopy(new PsiElement[] {element.getContainingFile()}, PlatformPackageUtil.getDirectory(element));
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
index 4dcdfe8..a0e5608 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
@@ -143,7 +143,7 @@
   private TitleIndexes myTitleIndexes;
   private Map<String, String> myConfigurables = new HashMap<String, String>();
 
-  private Alarm myAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, ApplicationManager.getApplication());
+  private Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, ApplicationManager.getApplication());
   private Alarm myUpdateAlarm = new Alarm(ApplicationManager.getApplication());
   private JBList myList;
   private JCheckBox myNonProjectCheckBox;
@@ -608,6 +608,7 @@
   }
 
   private void rebuildList(final String pattern) {
+    assert EventQueue.isDispatchThread() : "Must be EDT";
     if (myCalcThread != null && !myCurrentWorker.isProcessed()) {
       myCurrentWorker = myCalcThread.cancel();
     }
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
index c7a81cb..f9d4a75 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
@@ -189,7 +189,7 @@
   private final SplitterProportionsData splitterProportions = new SplitterProportionsDataImpl();
   private final MessageBusConnection myConnection;
   private final Map<String, Element> myUninitializedPaneState = new HashMap<String, Element>();
-  private final Map<String, SelectInTarget> mySelectInTargets = new HashMap<String, SelectInTarget>();
+  private final Map<String, SelectInTarget> mySelectInTargets = new LinkedHashMap<String, SelectInTarget>();
   private ContentManager myContentManager;
   private boolean myFoldersAlwaysOnTop = true;
 
diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/CreateScratchFileAction.java b/platform/lang-impl/src/com/intellij/ide/scratch/CreateScratchFileAction.java
new file mode 100644
index 0000000..a829cf8
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/scratch/CreateScratchFileAction.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.scratch;
+
+import com.intellij.lang.Language;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.ComboBox;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.CollectionComboBoxModel;
+import com.intellij.ui.ComboboxSpeedSearch;
+import com.intellij.ui.ListCellRendererWrapper;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author ignatov
+ */
+public class CreateScratchFileAction extends AnAction implements DumbAware {
+  private static final Set<String> FORBIDDEN_LANGUAGES = ContainerUtil.newHashSet("<Generic>", "$XSLT");
+
+  public CreateScratchFileAction() {
+    super("Create Scratch File...", "New Scratch File", null);
+  }
+
+  @Override
+  public void actionPerformed(AnActionEvent e) {
+    final Project project = e.getProject();
+    if (project == null) return;
+
+    MyDialog dialog = new MyDialog(project);
+    dialog.setResizable(false);
+    if (dialog.showAndGet()) {
+      Language language = dialog.getType();
+      VirtualFile file = ScratchpadManager.getInstance(project).createScratchFile(language);
+      if (file == null) return;
+      OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file);
+      FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
+    }
+  }
+
+  private static class MyDialog extends DialogWrapper {
+    @Nullable private Project myProject;
+    @NotNull  private JComboBox myComboBox;
+
+    protected MyDialog(@Nullable Project project) {
+      super(project);
+      myProject = project;
+      setTitle("Specify the Language");
+      init();
+    }
+
+    @Nullable
+    @Override
+    protected JComponent createCenterPanel() {
+      JPanel panel = new JPanel(new BorderLayout());
+      myComboBox = createCombo(getLanguages());
+      panel.add(myComboBox, BorderLayout.CENTER);
+      return panel;
+    }
+
+    @NotNull
+    public Language getType() {
+      return ((Language)myComboBox.getSelectedItem());
+    }
+
+    @NotNull
+    private JComboBox createCombo(@NotNull List<Language> languages) {
+      JComboBox jComboBox = new ComboBox(new CollectionComboBoxModel(languages));
+      jComboBox.setRenderer(new ListCellRendererWrapper<Language>() {
+        @Override
+        public void customize(JList list, Language lang, int index, boolean selected, boolean hasFocus) {
+          if (lang != null) {
+            setText(lang.getDisplayName());
+            LanguageFileType associatedLanguage = lang.getAssociatedFileType();
+            if (associatedLanguage != null) setIcon(associatedLanguage.getIcon());
+          }
+        }
+      });
+      new ComboboxSpeedSearch(jComboBox) {
+        @Override
+        protected String getElementText(Object element) {
+          return element instanceof Language ? ((Language)element).getDisplayName() : null;
+        }
+      };
+      Language previous = myProject != null ? ScratchpadManager.getInstance(myProject).getLatestLanguage() : null;
+      if (previous != null) {
+        jComboBox.setSelectedItem(previous);
+      }
+
+      return jComboBox;
+    }
+
+    @Nullable
+    @Override
+    public JComponent getPreferredFocusedComponent() {
+      return myComboBox;
+    }
+  }
+
+  @NotNull
+  private static List<Language> getLanguages() {
+    Set<Language> result = ContainerUtil.newTreeSet(new Comparator<Language>() {
+      @Override
+      public int compare(Language l1, Language l2) {
+        return l1.getDisplayName().compareTo(l2.getDisplayName());
+      }
+    });
+    for (Language lang : Language.getRegisteredLanguages()) {
+      if (!StringUtil.isEmpty(lang.getDisplayName())) result.add(lang);
+      for (Language dialect : lang.getDialects()) result.add(dialect);
+    }
+    return ContainerUtil.filter(result, new Condition<Language>() {
+      @Override
+      public boolean value(Language lang) {
+        String name = lang.getDisplayName();
+        return !StringUtil.isEmpty(name) && !FORBIDDEN_LANGUAGES.contains(name);
+      }
+    });
+  }
+}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadFileSystem.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadFileSystem.java
new file mode 100644
index 0000000..e643b62
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadFileSystem.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.scratch;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.presentation.Presentation;
+import com.intellij.ide.presentation.PresentationProvider;
+import com.intellij.lang.Language;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.openapi.vfs.VirtualFileSystem;
+import com.intellij.openapi.vfs.ex.dummy.DummyFileSystem;
+import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.ui.LayeredIcon;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.List;
+import java.util.Map;
+
+public class ScratchpadFileSystem extends DummyFileSystem {
+  private static final String PROTOCOL = "scratchpad";
+  private final Map<String, VirtualFile> myCachedFiles = ContainerUtil.newHashMap();
+
+  public static ScratchpadFileSystem getScratchFileSystem() {
+    return (ScratchpadFileSystem)VirtualFileManager.getInstance().getFileSystem(PROTOCOL);
+  }
+
+  public void removeByPrefix(@NotNull final String prefix) {
+    List<String> toRemove = ContainerUtil.findAll(myCachedFiles.keySet(), new Condition<String>() {
+      @Override
+      public boolean value(String s) {
+        return s.startsWith(prefix);
+      }
+    });
+    for (String s : toRemove) {
+      myCachedFiles.remove(s);
+    }
+  }
+
+  @Override
+  public VirtualFile findFileByPath(@NotNull String path) {
+    VirtualFile file = myCachedFiles.get(path);
+    if (file != null && file.isValid()) return file;
+    return null;
+  }
+
+  @NotNull
+  public VirtualFile addFile(@NotNull String name, @NotNull Language language, @NotNull String prefix) {
+    VirtualFile file = new MyLightVirtualFile(name, language, prefix);
+    myCachedFiles.put(file.getPath(), file);
+    return file;
+  }
+
+  @NotNull
+  @Override
+  public String getProtocol() {
+    return PROTOCOL;
+  }
+
+  @NotNull
+  @Override
+  public String extractPresentableUrl(@NotNull String path) {
+    String substring = StringUtil.substringAfter(path, "/");
+    return substring != null ? substring : super.extractPresentableUrl(path);
+  }
+
+  @Presentation(provider = ScratchPresentation.class)
+  private static class MyLightVirtualFile extends LightVirtualFile {
+    private final String myPrefix;
+
+    public MyLightVirtualFile(@NotNull String fileName, @NotNull Language language, @NotNull String projectPrefix) {
+      super(fileName, language, "");
+      myPrefix = projectPrefix;
+    }
+
+    @NotNull
+    @Override
+    public VirtualFileSystem getFileSystem() {
+      return getScratchFileSystem();
+    }
+
+    @NotNull
+    @Override
+    public String getPath() {
+      return myPrefix + super.getPath();
+    }
+  }
+
+  public static class ScratchPresentation extends PresentationProvider<MyLightVirtualFile> {
+    @Override
+    public Icon getIcon(@NotNull MyLightVirtualFile file) {
+      return LayeredIcon.create(file.getFileType().getIcon(), AllIcons.Actions.New);
+    }
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadManager.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadManager.java
new file mode 100644
index 0000000..53c988a
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadManager.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.scratch;
+
+import com.intellij.lang.Language;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class ScratchpadManager {
+  public static ScratchpadManager getInstance(@NotNull Project project) {
+    return ServiceManager.getService(project, ScratchpadManager.class);
+  }
+
+  @NotNull
+  public abstract VirtualFile createScratchFile(@NotNull Language language);
+
+  @Nullable
+  public abstract Language getLatestLanguage();
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadManagerImpl.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadManagerImpl.java
new file mode 100644
index 0000000..ed931e7
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchpadManagerImpl.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.scratch;
+
+import com.intellij.lang.Language;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+
+public class ScratchpadManagerImpl extends ScratchpadManager implements Disposable {
+  private final Project myProject;
+  private final Map<String, Integer> myExtensionsCounterMap = ContainerUtil.newHashMap();
+  private Language myLatestLanguage;
+
+  public ScratchpadManagerImpl(@NotNull Project project) {
+    myProject = project;
+  }
+
+  @NotNull
+  @Override
+  public VirtualFile createScratchFile(@NotNull final Language language) {
+    myLatestLanguage = language;
+    return ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
+      @Override
+      public VirtualFile compute() {
+        String name = generateFileName(language);
+        return ScratchpadFileSystem.getScratchFileSystem().addFile(name, language, calculatePrefix(ScratchpadManagerImpl.this.myProject));
+      }
+    });
+  }
+
+  @NotNull
+  private static String calculatePrefix(@NotNull Project project) {
+    return project.getLocationHash();
+  }
+
+  @Override
+  public Language getLatestLanguage() {
+    return myLatestLanguage;
+  }
+
+  @NotNull
+  private String generateFileName(@NotNull Language language) {
+    LanguageFileType associatedFileType = language.getAssociatedFileType();
+    String ext = associatedFileType != null ? associatedFileType.getDefaultExtension() : "unknown";
+    Integer prev = myExtensionsCounterMap.get(ext);
+    int updated = prev == null ? 1 : ++prev;
+    myExtensionsCounterMap.put(ext, updated);
+    String index = updated == 1 ? "" : updated + ".";
+    return "scratch." + index + ext;
+  }
+
+  @Override
+  public void dispose() {
+    ScratchpadFileSystem.getScratchFileSystem().removeByPrefix(calculatePrefix(myProject));
+  }
+}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/ide/util/PlatformPackageUtil.java b/platform/lang-impl/src/com/intellij/ide/util/PlatformPackageUtil.java
index 01ad4cb..30d4933 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/PlatformPackageUtil.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/PlatformPackageUtil.java
@@ -16,7 +16,6 @@
 package com.intellij.ide.util;
 
 import com.intellij.ide.IdeBundle;
-import com.intellij.lang.injection.InjectedLanguageManager;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.module.Module;
@@ -35,6 +34,7 @@
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiManager;
+import com.intellij.psi.impl.source.resolve.FileContextUtil;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.search.GlobalSearchScopes;
 import com.intellij.util.*;
@@ -276,12 +276,10 @@
   }
 
   @Nullable
-  public static PsiDirectory getDirectory(PsiElement element) {
-    PsiFile file = element.getContainingFile();
-    final PsiElement context = InjectedLanguageManager.getInstance(file.getProject()).getInjectionHost(file);
-    if (context != null) {
-      file = context.getContainingFile();
-    }
-    return file.getParent();
+  public static PsiDirectory getDirectory(@Nullable PsiElement element) {
+    if (element == null) return null;
+    // handle injection and fragment editor
+    PsiFile file = FileContextUtil.getContextFile(element);
+    return file == null ? null : file.getContainingDirectory();
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java
index cee529a..33b417d 100644
--- a/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java
+++ b/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java
@@ -17,16 +17,18 @@
 package com.intellij.injected.editor;
 
 import com.intellij.openapi.editor.*;
+import com.intellij.openapi.editor.event.CaretAdapter;
 import com.intellij.openapi.editor.event.CaretEvent;
 import com.intellij.openapi.editor.event.CaretListener;
 import com.intellij.openapi.editor.ex.EditorEx;
 import com.intellij.openapi.editor.markup.TextAttributes;
-import com.intellij.openapi.util.Segment;
-import com.intellij.openapi.util.TextRange;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
 
 /**
  * @author Alexey
@@ -102,7 +104,7 @@
   private final ListenerWrapperMap<CaretListener> myCaretListeners = new ListenerWrapperMap<CaretListener>();
   @Override
   public void addCaretListener(@NotNull final CaretListener listener) {
-    CaretListener wrapper = new CaretListener() {
+    CaretListener wrapper = new CaretAdapter() {
       @Override
       public void caretPositionChanged(CaretEvent e) {
         if (!myEditorWindow.getDocument().isValid()) return; // injected document can be destroyed by now
@@ -163,6 +165,11 @@
     return createInjectedCaret(myDelegate.getPrimaryCaret());
   }
 
+  @Override
+  public int getCaretCount() {
+    return myDelegate.getCaretCount();
+  }
+
   @NotNull
   @Override
   public List<Caret> getAllCarets() {
@@ -204,17 +211,14 @@
   }
 
   @Override
-  public void setCaretsAndSelections(@NotNull List<LogicalPosition> caretPositions, @NotNull List<? extends Segment> selections) {
-    List<LogicalPosition> convertedPositions = new ArrayList<LogicalPosition>(caretPositions);
-    for (LogicalPosition position : caretPositions) {
-      convertedPositions.add(myEditorWindow.injectedToHost(position));
+  public void setCaretsAndSelections(@NotNull List<CaretState> caretStates) {
+    List<CaretState> convertedStates = new ArrayList<CaretState>(caretStates.size());
+    for (CaretState state : caretStates) {
+      convertedStates.add(new CaretState(state.getCaretPosition() == null ? null : myEditorWindow.injectedToHost(state.getCaretPosition()),
+                                         state.getSelectionStart() == null ? null : myEditorWindow.injectedToHost(state.getSelectionStart()),
+                                         state.getSelectionEnd() == null ? null : myEditorWindow.injectedToHost(state.getSelectionEnd())));
     }
-    List<Segment> convertedSelections = new ArrayList<Segment>(selections.size());
-    for (Segment selection : selections) {
-      convertedSelections.add(new TextRange(myEditorWindow.getDocument().injectedToHost(selection.getStartOffset()),
-                                            myEditorWindow.getDocument().injectedToHost(selection.getEndOffset())));
-    }
-    myDelegate.setCaretsAndSelections(convertedPositions, convertedSelections);
+    myDelegate.setCaretsAndSelections(convertedStates);
   }
 
   private InjectedCaret createInjectedCaret(Caret caret) {
diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java
index 124b5d6..dfaa650 100644
--- a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java
+++ b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -34,7 +34,6 @@
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.actionSystem.DataProvider;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.application.AccessToken;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
@@ -1211,7 +1210,7 @@
     myEditor.setHighlighter(EditorHighlighterFactory.getInstance().createEditorHighlighter(myProject, lightFile));
   }
 
-  private class EditorListener implements CaretListener, SelectionListener, DocumentListener {
+  private class EditorListener extends CaretAdapter implements SelectionListener, DocumentListener {
     @Override
     public void caretPositionChanged(CaretEvent e) {
       if (!available() || myEditor.getSelectionModel().hasSelection()) return;
diff --git a/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffPreviewPanel.java b/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffPreviewPanel.java
index 9e227b0..9e32958 100644
--- a/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffPreviewPanel.java
+++ b/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffPreviewPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -165,6 +165,16 @@
     public void caretPositionChanged(CaretEvent e) {
       select(MergeSearchHelper.findChangeAt(e, getMergePanel(), myIndex));
     }
+
+    @Override
+    public void caretAdded(CaretEvent e) {
+
+    }
+
+    @Override
+    public void caretRemoved(CaretEvent e) {
+
+    }
   }
 
   @Override
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
new file mode 100644
index 0000000..81965ba
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor.actions;
+
+import com.intellij.find.FindManager;
+import com.intellij.find.FindModel;
+import com.intellij.find.FindResult;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.editor.actionSystem.EditorAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.Nullable;
+
+public class SelectAllOccurrencesAction extends EditorAction {
+  protected SelectAllOccurrencesAction() {
+    super(new Handler());
+  }
+
+  private static class Handler extends SelectOccurrencesActionHandler {
+    @Override
+    public boolean isEnabled(Editor editor, DataContext dataContext) {
+      return super.isEnabled(editor, dataContext) && editor.getProject() != null && editor.getCaretModel().supportsMultipleCarets();
+    }
+
+    @Override
+    public void execute(Editor editor, @Nullable Caret c, DataContext dataContext) {
+      Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
+
+      if (!caret.hasSelection()) {
+        TextRange wordSelectionRange = getSelectionRange(editor, caret);
+        if (wordSelectionRange != null) {
+          setSelection(editor, caret, wordSelectionRange);
+        }
+      }
+
+      String selectedText = caret.getSelectedText();
+      Project project = editor.getProject();
+      if (project == null || selectedText == null) {
+        return;
+      }
+
+      int caretShiftFromSelectionStart = caret.getOffset() - caret.getSelectionStart();
+      FindManager findManager = FindManager.getInstance(project);
+
+      FindModel model = new FindModel();
+      model.setStringToFind(selectedText);
+      model.setCaseSensitive(true);
+      model.setWholeWordsOnly(true);
+
+      int searchStartOffset = 0;
+      FindResult findResult = findManager.findString(editor.getDocument().getCharsSequence(), searchStartOffset, model);
+      while (findResult.isStringFound()) {
+        int newCaretOffset = caretShiftFromSelectionStart + findResult.getStartOffset();
+        EditorActionUtil.makePositionVisible(editor, newCaretOffset);
+        Caret newCaret = editor.getCaretModel().addCaret(editor.offsetToVisualPosition(newCaretOffset));
+        if (newCaret != null) {
+          setSelection(editor, newCaret, findResult);
+        }
+        findResult = findManager.findString(editor.getDocument().getCharsSequence(), findResult.getEndOffset(), model);
+      }
+      editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+    }
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
index 81a7851..0063a9f 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
@@ -15,37 +15,24 @@
  */
 package com.intellij.openapi.editor.actions;
 
-import com.intellij.codeInsight.editorActions.SelectWordUtil;
-import com.intellij.codeInsight.hint.HintManager;
-import com.intellij.codeInsight.hint.HintManagerImpl;
-import com.intellij.codeInsight.hint.HintUtil;
-import com.intellij.find.FindBundle;
 import com.intellij.find.FindManager;
 import com.intellij.find.FindModel;
 import com.intellij.find.FindResult;
-import com.intellij.openapi.editor.EditorLastActionTracker;
 import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.IdeActions;
 import com.intellij.openapi.editor.Caret;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.ScrollType;
 import com.intellij.openapi.editor.actionSystem.EditorAction;
-import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.TextRange;
-import com.intellij.ui.LightweightHint;
 import org.jetbrains.annotations.Nullable;
 
 public class SelectNextOccurrenceAction extends EditorAction {
-  private static final Key<Boolean> NOT_FOUND = Key.create("select.next.occurence.not.found");
-  private static final Key<Boolean> WHOLE_WORDS = Key.create("select.next.occurence.whole.words");
-
   protected SelectNextOccurrenceAction() {
     super(new Handler());
   }
 
-  static class Handler extends EditorActionHandler {
+  static class Handler extends SelectOccurrencesActionHandler {
     @Override
     public boolean isEnabled(Editor editor, DataContext dataContext) {
       return super.isEnabled(editor, dataContext) && editor.getProject() != null && editor.getCaretModel().supportsMultipleCarets();
@@ -54,9 +41,7 @@
     @Override
     public void execute(Editor editor, @Nullable Caret c, DataContext dataContext) {
       Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
-      TextRange wordSelectionRange = SelectWordUtil.getWordSelectionRange(editor.getDocument().getCharsSequence(),
-                                                                          caret.getOffset(),
-                                                                          SelectWordUtil.JAVA_IDENTIFIER_PART_CONDITION);
+      TextRange wordSelectionRange = getSelectionRange(editor, caret);
       boolean notFoundPreviously = getAndResetNotFoundStatus(editor);
       boolean wholeWordSearch = isWholeWordSearch(editor);
       if (caret.hasSelection()) {
@@ -68,7 +53,7 @@
         FindManager findManager = FindManager.getInstance(project);
 
         FindModel model = new FindModel();
-        model.setStringToFind(caret.getSelectedText());
+        model.setStringToFind(selectedText);
         model.setCaseSensitive(true);
         model.setWholeWordsOnly(wholeWordSearch);
 
@@ -102,50 +87,5 @@
       }
       editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
     }
-
-    private static void setSelection(Editor editor, Caret caret, TextRange selectionRange) {
-      EditorActionUtil.makePositionVisible(editor, selectionRange.getStartOffset());
-      EditorActionUtil.makePositionVisible(editor, selectionRange.getEndOffset());
-      caret.setSelection(selectionRange.getStartOffset(), selectionRange.getEndOffset());
-    }
-
-
-    private static void showHint(final Editor editor) {
-      String message = FindBundle.message("select.next.occurence.not.found.message");
-      final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message));
-      HintManagerImpl.getInstanceImpl().showEditorHint(hint,
-                                                       editor,
-                                                       HintManager.UNDER,
-                                                       HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING,
-                                                       0,
-                                                       false);
-    }
-
-    static boolean getAndResetNotFoundStatus(Editor editor) {
-      boolean status = editor.getUserData(NOT_FOUND) != null;
-      editor.putUserData(NOT_FOUND, null);
-      return status && isRepeatedActionInvocation();
-    }
-
-    private static void setNotFoundStatus(Editor editor) {
-      editor.putUserData(NOT_FOUND, Boolean.TRUE);
-    }
-
-    private static boolean isWholeWordSearch(Editor editor) {
-      if (!isRepeatedActionInvocation()) {
-        editor.putUserData(WHOLE_WORDS, null);
-      }
-      Boolean value = editor.getUserData(WHOLE_WORDS);
-      return value != null;
-    }
-
-    private static void setWholeWordSearch(Editor editor, boolean isWholeWordSearch) {
-      editor.putUserData(WHOLE_WORDS, isWholeWordSearch);
-    }
-
-    private static boolean isRepeatedActionInvocation() {
-      String lastActionId = EditorLastActionTracker.getInstance().getLastActionId();
-      return IdeActions.ACTION_SELECT_NEXT_OCCURENCE.equals(lastActionId) || IdeActions.ACTION_UNSELECT_LAST_OCCURENCE.equals(lastActionId);
-    }
   }
 }
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
new file mode 100644
index 0000000..c43eae7
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor.actions;
+
+import com.intellij.codeInsight.editorActions.SelectWordUtil;
+import com.intellij.codeInsight.hint.HintManager;
+import com.intellij.codeInsight.hint.HintManagerImpl;
+import com.intellij.codeInsight.hint.HintUtil;
+import com.intellij.find.FindBundle;
+import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorLastActionTracker;
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.ui.LightweightHint;
+import org.jetbrains.annotations.Nullable;
+
+abstract public class SelectOccurrencesActionHandler extends EditorActionHandler {
+
+  private static final Key<Boolean> NOT_FOUND = Key.create("select.next.occurence.not.found");
+  private static final Key<Boolean> WHOLE_WORDS = Key.create("select.next.occurence.whole.words");
+
+  protected static void setSelection(Editor editor, Caret caret, TextRange selectionRange) {
+    EditorActionUtil.makePositionVisible(editor, selectionRange.getStartOffset());
+    EditorActionUtil.makePositionVisible(editor, selectionRange.getEndOffset());
+    caret.setSelection(selectionRange.getStartOffset(), selectionRange.getEndOffset());
+  }
+
+  protected static void showHint(final Editor editor) {
+    String message = FindBundle.message("select.next.occurence.not.found.message");
+    final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message));
+    HintManagerImpl.getInstanceImpl().showEditorHint(hint,
+                                                     editor,
+                                                     HintManager.UNDER,
+                                                     HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING,
+                                                     0,
+                                                     false);
+  }
+
+  protected static boolean getAndResetNotFoundStatus(Editor editor) {
+    boolean status = editor.getUserData(NOT_FOUND) != null;
+    editor.putUserData(NOT_FOUND, null);
+    return status && isRepeatedActionInvocation();
+  }
+
+  protected static void setNotFoundStatus(Editor editor) {
+    editor.putUserData(NOT_FOUND, Boolean.TRUE);
+  }
+
+  protected static boolean isWholeWordSearch(Editor editor) {
+    if (!isRepeatedActionInvocation()) {
+      editor.putUserData(WHOLE_WORDS, null);
+    }
+    Boolean value = editor.getUserData(WHOLE_WORDS);
+    return value != null;
+  }
+
+  @Nullable
+  protected static TextRange getSelectionRange(Editor editor, Caret caret) {
+    return SelectWordUtil.getWordSelectionRange(editor.getDocument().getCharsSequence(),
+                                                caret.getOffset(),
+                                                SelectWordUtil.JAVA_IDENTIFIER_PART_CONDITION);
+  }
+
+  protected static void setWholeWordSearch(Editor editor, boolean isWholeWordSearch) {
+    editor.putUserData(WHOLE_WORDS, isWholeWordSearch);
+  }
+
+  protected static boolean isRepeatedActionInvocation() {
+    String lastActionId = EditorLastActionTracker.getInstance().getLastActionId();
+    return IdeActions.ACTION_SELECT_NEXT_OCCURENCE.equals(lastActionId) || IdeActions.ACTION_UNSELECT_PREVIOUS_OCCURENCE.equals(lastActionId);
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectLastOccurrenceAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
similarity index 80%
rename from platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectLastOccurrenceAction.java
rename to platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
index 192e41c..489aa4e 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectLastOccurrenceAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
@@ -20,15 +20,14 @@
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.ScrollType;
 import com.intellij.openapi.editor.actionSystem.EditorAction;
-import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
 import org.jetbrains.annotations.Nullable;
 
-public class UnselectLastOccurrenceAction extends EditorAction {
-  protected UnselectLastOccurrenceAction() {
+public class UnselectPreviousOccurrenceAction extends EditorAction {
+  protected UnselectPreviousOccurrenceAction() {
     super(new Handler());
   }
 
-  private static class Handler extends EditorActionHandler {
+  private static class Handler extends SelectOccurrencesActionHandler {
     @Override
     public boolean isEnabled(Editor editor, DataContext dataContext) {
       return super.isEnabled(editor, dataContext) && editor.getCaretModel().supportsMultipleCarets();
@@ -36,13 +35,13 @@
 
     @Override
     public void execute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
-      if (editor.getCaretModel().getAllCarets().size() > 1) {
+      if (editor.getCaretModel().getCaretCount() > 1) {
         editor.getCaretModel().removeCaret(editor.getCaretModel().getPrimaryCaret());
       }
       else {
         editor.getSelectionModel().removeSelection();
       }
-      SelectNextOccurrenceAction.Handler.getAndResetNotFoundStatus(editor);
+      getAndResetNotFoundStatus(editor);
       editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
     }
   }
diff --git a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java
index 4a94d1a..8018876 100644
--- a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java
+++ b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java
@@ -33,6 +33,7 @@
 public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory {
 
   public static final LayeredIcon ENFORCED_PLAIN_TEXT_ICON = new LayeredIcon(2);
+  public static final String ENFORCED_PLAIN_TEXT = "Enforced Plain Text";
 
   static {
     ENFORCED_PLAIN_TEXT_ICON.setIcon(AllIcons.FileTypes.Text, 0);
@@ -59,13 +60,13 @@
       @NotNull
       @Override
       public String getName() {
-        return "Enforced Plain Text";
+        return ENFORCED_PLAIN_TEXT;
       }
 
       @NotNull
       @Override
       public String getDescription() {
-        return "Enforced Plain Text";
+        return ENFORCED_PLAIN_TEXT;
       }
 
       @NotNull
diff --git a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java
index 420ed29..e8a18e4 100644
--- a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java
+++ b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java
@@ -26,8 +26,8 @@
 import com.intellij.openapi.project.ProjectManagerListener;
 import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
 import com.intellij.openapi.util.EmptyRunnable;
-import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileWithId;
 import com.intellij.util.containers.ConcurrentHashMap;
 import com.intellij.util.indexing.FileBasedIndex;
 import org.jetbrains.annotations.NotNull;
@@ -44,18 +44,21 @@
  */
 public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener {
   private final Map<Project, Collection<VirtualFile>> myPlainTextFileSets = new ConcurrentHashMap<Project, Collection<VirtualFile>>();
-  private final Ref<Boolean> mySetsInitialized = new Ref<Boolean>(false);
+  private volatile boolean mySetsInitialized = false;
+  private static final Object LOCK = new Object();
 
   public EnforcedPlainTextFileTypeManager() {
     ProjectManager.getInstance().addProjectManagerListener(this);
   }
 
   public boolean isMarkedAsPlainText(VirtualFile file) {
-    if (file.isDirectory()) return false;
-    synchronized (mySetsInitialized) {
-      if (!mySetsInitialized.get()) {
-        initPlainTextFileSets();
-        mySetsInitialized.set(true);
+    if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false;
+    if (!mySetsInitialized) {
+      synchronized (LOCK) {
+        if (!mySetsInitialized) {
+          initPlainTextFileSets();
+          mySetsInitialized = true;
+        }
       }
     }
     for (Project project : myPlainTextFileSets.keySet()) {
@@ -73,7 +76,7 @@
   }
 
   public static boolean isApplicableFor(@NotNull VirtualFile file) {
-    if (file.isDirectory()) return false;
+    if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false;
     FileType originalType = FileTypeManager.getInstance().getFileTypeByFileName(file.getName());
     return !originalType.isBinary() && originalType != FileTypes.PLAIN_TEXT && originalType != StdFileTypes.JAVA;
   }
@@ -95,7 +98,7 @@
     fireRootsChanged(filesToSync, isPlainText);
   }
 
-  private static void fireRootsChanged(final Collection<VirtualFile> files, final boolean isAdded) {
+  private void fireRootsChanged(final Collection<VirtualFile> files, final boolean isAdded) {
     ApplicationManager.getApplication().runWriteAction(new Runnable() {
       @Override
       public void run() {
@@ -104,6 +107,7 @@
           ProjectPlainTextFileTypeManager projectPlainTextFileTypeManager = ProjectPlainTextFileTypeManager.getInstance(project);
           for (VirtualFile file : files) {
             if (projectPlainTextFileTypeManager.hasProjectContaining(file)) {
+              ensureProjectFileSetAdded(project, projectPlainTextFileTypeManager);
               if (isAdded) {
                 projectPlainTextFileTypeManager.addFile(file);
               }
@@ -117,6 +121,13 @@
     });
   }
 
+  private void ensureProjectFileSetAdded(@NotNull Project project,
+                                         @NotNull ProjectPlainTextFileTypeManager projectPlainTextFileTypeManager) {
+    if (!myPlainTextFileSets.containsKey(project)) {
+      myPlainTextFileSets.put(project, projectPlainTextFileTypeManager.getFiles());
+    }
+  }
+
   private static class EnforcedPlainTextFileTypeManagerHolder {
     private static final EnforcedPlainTextFileTypeManager ourInstance = ServiceManager.getService(EnforcedPlainTextFileTypeManager.class);
   }
diff --git a/platform/lang-impl/src/com/intellij/openapi/file/exclude/PersistentFileSetManager.java b/platform/lang-impl/src/com/intellij/openapi/file/exclude/PersistentFileSetManager.java
index aab5c78..67b19d6 100644
--- a/platform/lang-impl/src/com/intellij/openapi/file/exclude/PersistentFileSetManager.java
+++ b/platform/lang-impl/src/com/intellij/openapi/file/exclude/PersistentFileSetManager.java
@@ -19,6 +19,7 @@
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.openapi.vfs.VirtualFileWithId;
 import com.intellij.util.containers.HashSet;
 import org.jdom.Attribute;
 import org.jdom.Element;
@@ -36,7 +37,7 @@
   private final Set<VirtualFile> myFiles = new HashSet<VirtualFile>();
   
   protected boolean addFile(VirtualFile file) {
-    if (file.isDirectory()) return false;
+    if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false;
     myFiles.add(file);
     return true;
   }
diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java
index f32a372..af4484a 100644
--- a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java
+++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java
@@ -262,51 +262,61 @@
     return getStateStore().getOptionValue(optionName);
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleScope() {
     return myModuleScopeProvider.getModuleScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleScope(boolean includeTests) {
     return myModuleScopeProvider.getModuleScope(includeTests);
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithLibrariesScope() {
     return myModuleScopeProvider.getModuleWithLibrariesScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependenciesScope() {
     return myModuleScopeProvider.getModuleWithDependenciesScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleContentScope() {
     return myModuleScopeProvider.getModuleContentScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleContentWithDependenciesScope() {
     return myModuleScopeProvider.getModuleContentWithDependenciesScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependenciesAndLibrariesScope(boolean includeTests) {
     return myModuleScopeProvider.getModuleWithDependenciesAndLibrariesScope(includeTests);
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependentsScope() {
     return myModuleScopeProvider.getModuleWithDependentsScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleTestsWithDependentsScope() {
     return myModuleScopeProvider.getModuleTestsWithDependentsScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleRuntimeScope(boolean includeTests) {
     return myModuleScopeProvider.getModuleRuntimeScope(includeTests);
diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java
index cd8c1bf..40e1e79 100644
--- a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java
+++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java
@@ -18,6 +18,7 @@
 import com.intellij.ide.todo.TodoFilter;
 import com.intellij.ide.todo.TodoIndexPatternProvider;
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
 import com.intellij.openapi.diff.impl.fragments.LineFragment;
@@ -302,7 +303,8 @@
 
   private static ArrayList<LineFragment> getLineFragments(final String fileName, String beforeContent, String afterContent) throws VcsException {
     try {
-      DiffFragment[] woFormattingBlocks = DiffPolicy.LINES_WO_FORMATTING.buildFragments(beforeContent, afterContent);
+      DiffFragment[] woFormattingBlocks =
+        DiffPolicy.LINES_WO_FORMATTING.buildFragments(DiffString.create(beforeContent), DiffString.create(afterContent));
       DiffFragment[] step1lineFragments =
         new DiffCorrection.TrueLineBlocks(ComparisonPolicy.IGNORE_SPACE).correctAndNormalize(woFormattingBlocks);
       return new DiffFragmentsProcessor().process(step1lineFragments);
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeIndex.java b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeIndex.java
index 43bc2fa..bc1254c 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeIndex.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -108,6 +108,7 @@
     };
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<Key> getKeyDescriptor() {
     return new KeyDescriptor<Key>() {
@@ -122,24 +123,25 @@
       }
 
       @Override
-      public void save(DataOutput out, Key value) throws IOException {
+      public void save(@NotNull DataOutput out, Key value) throws IOException {
         out.writeBoolean(value.isInclude());
         value.writeValue(out);
       }
 
       @Override
-      public Key read(DataInput in) throws IOException {
+      public Key read(@NotNull DataInput in) throws IOException {
         boolean isInclude = in.readBoolean();
         return isInclude ? IncludeKey.read(in) : new FileKey(in.readInt());
       }
     };
   }
 
+  @NotNull
   @Override
   public DataExternalizer<List<FileIncludeInfoImpl>> getValueExternalizer() {
     return new DataExternalizer<List<FileIncludeInfoImpl>>() {
       @Override
-      public void save(DataOutput out, List<FileIncludeInfoImpl> value) throws IOException {
+      public void save(@NotNull DataOutput out, List<FileIncludeInfoImpl> value) throws IOException {
         out.writeInt(value.size());
         for (FileIncludeInfoImpl info : value) {
           out.writeUTF(info.path);
@@ -150,7 +152,7 @@
       }
 
       @Override
-      public List<FileIncludeInfoImpl> read(DataInput in) throws IOException {
+      public List<FileIncludeInfoImpl> read(@NotNull DataInput in) throws IOException {
         int size = in.readInt();
         ArrayList<FileIncludeInfoImpl> infos = new ArrayList<FileIncludeInfoImpl>(size);
         for (int i = 0; i < size; i++) {
@@ -161,11 +163,12 @@
     };
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return new FileBasedIndex.FileTypeSpecificInputFilter() {
       @Override
-      public boolean acceptInput(VirtualFile file) {
+      public boolean acceptInput(@NotNull VirtualFile file) {
         if (file.getFileSystem() == JarFileSystem.getInstance()) {
           return false;
         }
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java
index 19f1aa2..8fa6c57 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java
@@ -55,6 +55,7 @@
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.testFramework.LightVirtualFile;
 import com.intellij.util.SmartList;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -214,16 +215,7 @@
       Language forcedLanguage = myContextElement.getUserData(InjectedFileViewProvider.LANGUAGE_FOR_INJECTED_COPY_KEY);
       myLanguage = forcedLanguage == null ? LanguageSubstitutors.INSTANCE.substituteLanguage(myLanguage, virtualFile, myProject) : forcedLanguage;
 
-      DocumentImpl decodedDocument;
-      if (StringUtil.indexOf(outChars, '\r') == -1) {
-        decodedDocument = new DocumentImpl(outChars);
-      }
-      else {
-        decodedDocument = new DocumentImpl("", true);
-        decodedDocument.setAcceptSlashR(true);
-        decodedDocument.replaceString(0,0,outChars);
-      }
-      FileDocumentManagerImpl.registerDocument(decodedDocument, virtualFile);
+      createDocument(virtualFile);
 
       InjectedFileViewProvider viewProvider = new InjectedFileViewProvider(myPsiManager, virtualFile, documentWindow, myLanguage);
       ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(myLanguage);
@@ -307,6 +299,14 @@
     }
   }
 
+  @NotNull
+  private static DocumentEx createDocument(@NotNull LightVirtualFile virtualFile) {
+    CharSequence content = virtualFile.getContent();
+    DocumentImpl document = new DocumentImpl(content, StringUtil.indexOf(content, '\r') >= 0, false);
+    FileDocumentManagerImpl.registerDocument(document, virtualFile);
+    return document;
+  }
+
   // returns true if shreds were set, false if old ones were reused
   private static boolean cacheEverything(@NotNull Place place,
                                          @NotNull DocumentWindowImpl documentWindow,
diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java
index 0877a65..6682da3 100644
--- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.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.
@@ -19,6 +19,7 @@
  */
 package com.intellij.psi.stubs;
 
+import com.intellij.lang.Language;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.components.*;
@@ -26,12 +27,16 @@
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.LanguageFileType;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.NotNullComputable;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.newvfs.ManagingFS;
 import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
+import com.intellij.psi.LanguageSubstitutors;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
@@ -53,7 +58,6 @@
 
 import java.io.*;
 import java.util.*;
-import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.Lock;
 
@@ -161,7 +165,7 @@
 
   private static class StubIdExternalizer implements DataExternalizer<StubIdList> {
     @Override
-    public void save(final DataOutput out, @NotNull final StubIdList value) throws IOException {
+    public void save(@NotNull final DataOutput out, @NotNull final StubIdList value) throws IOException {
       int size = value.size();
       if (size == 0) {
         DataInputOutputUtil.writeINT(out, Integer.MAX_VALUE);
@@ -179,7 +183,7 @@
 
     @NotNull
     @Override
-    public StubIdList read(final DataInput in) throws IOException {
+    public StubIdList read(@NotNull final DataInput in) throws IOException {
       int size = DataInputOutputUtil.readINT(in);
       if (size == Integer.MAX_VALUE) {
         return new StubIdList();
@@ -424,9 +428,10 @@
   public <K> void updateIndex(@NotNull StubIndexKey key, int fileId, @NotNull final Map<K, StubIdList> oldValues, @NotNull Map<K, StubIdList> newValues) {
     try {
       final MyIndex<K> index = (MyIndex<K>)myIndices.get(key);
-      index.updateWithMap(fileId, newValues, new Callable<Collection<K>>() {
+      index.updateWithMap(fileId, newValues, new NotNullComputable<Collection<K>>() {
+        @NotNull
         @Override
-        public Collection<K> call() throws Exception {
+        public Collection<K> compute() {
           return oldValues.keySet();
         }
       });
@@ -445,7 +450,7 @@
     @Override
     public void updateWithMap(final int inputId,
                               @NotNull final Map<K, StubIdList> newData,
-                              @NotNull Callable<Collection<K>> oldKeysGetter) throws StorageException {
+                              @NotNull NotNullComputable<Collection<K>> oldKeysGetter) throws StorageException {
       super.updateWithMap(inputId, newData, oldKeysGetter);
     }
   }
@@ -465,8 +470,13 @@
     out.printf("\nfile: %s\npsiElement: %s\nrequiredClass: %s\nactualClass: %s",
                file, psi, requiredClass, psi.getClass());
 
-    out.printf("\nvirtualFile: size:%s; stamp:%s; modCount:%s",
-               file.getLength(), file.getModificationStamp(), file.getModificationCount());
+    FileType fileType = file.getFileType();
+    Language language = fileType instanceof LanguageFileType ?
+                        LanguageSubstitutors.INSTANCE.substituteLanguage(((LanguageFileType)fileType).getLanguage(), file, psi.getProject()) :
+                        Language.ANY;
+    out.printf("\nvirtualFile: size:%s; stamp:%s; modCount:%s; fileType:%s; language:%s",
+               file.getLength(), file.getModificationStamp(), file.getModificationCount(),
+               fileType.getName(), language.getID());
 
     Document document = FileDocumentManager.getInstance().getCachedDocument(file);
     if (document != null) {
@@ -478,8 +488,9 @@
 
     PsiFile psiFile = psi.getManager().findFile(file);
     if (psiFile != null) {
-      out.printf("\npsiFile: size:%s; stamp:%s; class:%s",
-                 psiFile.getTextLength(), psiFile.getViewProvider().getModificationStamp(), psiFile.getClass().getName());
+      out.printf("\npsiFile: size:%s; stamp:%s; class:%s; language:%s",
+                 psiFile.getTextLength(), psiFile.getViewProvider().getModificationStamp(), psiFile.getClass().getName(),
+                 psiFile.getLanguage().getID());
     }
 
     StubTree stub = psiFile instanceof PsiFileWithStubSupport ? ((PsiFileWithStubSupport)psiFile).getStubTree() : null;
diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java
index 93e2b35..4cb07a6 100644
--- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java
+++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -23,6 +23,7 @@
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.fileTypes.FileTypeManager;
 import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.util.NotNullComputable;
 import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.newvfs.FileAttribute;
@@ -37,7 +38,6 @@
 
 import java.io.*;
 import java.util.*;
-import java.util.concurrent.Callable;
 
 /*
  * @author max
@@ -54,13 +54,13 @@
 
   private static final DataExternalizer<SerializedStubTree> KEY_EXTERNALIZER = new DataExternalizer<SerializedStubTree>() {
     @Override
-    public void save(final DataOutput out, @NotNull final SerializedStubTree v) throws IOException {
+    public void save(@NotNull final DataOutput out, @NotNull final SerializedStubTree v) throws IOException {
       v.write(out);
     }
 
     @NotNull
     @Override
-    public SerializedStubTree read(final DataInput in) throws IOException {
+    public SerializedStubTree read(@NotNull final DataInput in) throws IOException {
       return new SerializedStubTree(in);
     }
   };
@@ -226,11 +226,11 @@
 
   @NotNull
   @Override
-  public UpdatableIndex<Integer, SerializedStubTree, FileContent> createIndexImplementation(final ID<Integer, SerializedStubTree> indexId, @NotNull final FileBasedIndex owner, @NotNull IndexStorage<Integer, SerializedStubTree> storage)
+  public UpdatableIndex<Integer, SerializedStubTree, FileContent> createIndexImplementation(@NotNull final ID<Integer, SerializedStubTree> indexId, @NotNull final FileBasedIndex owner, @NotNull IndexStorage<Integer, SerializedStubTree> storage)
     throws StorageException {
     if (storage instanceof MemoryIndexStorage) {
       final MemoryIndexStorage<Integer, SerializedStubTree> memStorage = (MemoryIndexStorage<Integer, SerializedStubTree>)storage;
-      memStorage.addBufferingStateListsner(new MemoryIndexStorage.BufferingStateListener() {
+      memStorage.addBufferingStateListener(new MemoryIndexStorage.BufferingStateListener() {
         @Override
         public void bufferingStateChanged(final boolean newState) {
           ((StubIndexImpl)StubIndex.getInstance()).setDataBufferingEnabled(newState);
@@ -294,7 +294,7 @@
     @Override
     protected void updateWithMap(final int inputId,
                                  @NotNull final Map<Integer, SerializedStubTree> newData,
-                                 @NotNull Callable<Collection<Integer>> oldKeysGetter)
+                                 @NotNull NotNullComputable<Collection<Integer>> oldKeysGetter)
       throws StorageException {
 
       checkNameStorage();
diff --git a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java
index 773bb2b..2532a92 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java
@@ -465,7 +465,7 @@
       PsiDocumentManager.getInstance(myProject).commitAllDocuments();
       RefactoringListenerManagerImpl listenerManager = (RefactoringListenerManagerImpl)RefactoringListenerManager.getInstance(myProject);
       myTransaction = listenerManager.startTransaction();
-      final Map<RefactoringHelper, Object> preparedData = new HashMap<RefactoringHelper, Object>();
+      final Map<RefactoringHelper, Object> preparedData = new LinkedHashMap<RefactoringHelper, Object>();
       final Runnable prepareHelpersRunnable = new Runnable() {
         @Override
         public void run() {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodSignatureEditor.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodSignatureEditor.java
index 83122e1..d5d4812 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodSignatureEditor.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodSignatureEditor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -21,10 +21,7 @@
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.EditorFactory;
 import com.intellij.openapi.editor.LogicalPosition;
-import com.intellij.openapi.editor.event.CaretEvent;
-import com.intellij.openapi.editor.event.CaretListener;
-import com.intellij.openapi.editor.event.DocumentAdapter;
-import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.editor.event.*;
 import com.intellij.openapi.editor.impl.CaretModelImpl;
 import com.intellij.openapi.editor.impl.EditorImpl;
 import com.intellij.openapi.util.Key;
@@ -163,7 +160,7 @@
           CodeStyleManager.getInstance(getProject()).reformatText(myFile, range.getStartOffset(), range.getEndOffset());
         }
       });
-      editor.getCaretModel().addCaretListener(new CaretListener() {
+      editor.getCaretModel().addCaretListener(new CaretAdapter() {
         @Override
         public void caretPositionChanged(CaretEvent e) {
           createFromString();
diff --git a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java
index 1a0882a..5314b49 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java
@@ -101,7 +101,9 @@
         PsiFile file = (PsiFile)elements[0];
         String url = shortenPath(file.getVirtualFile());
         text = RefactoringBundle.message(doClone ? "copy.files.clone.file.0" : "copy.files.copy.file.0", url);
-        final String fileName = file.getName();
+        // keep extensions (dots) and spaces, e.g. fragment file name will be "HTML Fragment (my.sql_61).html"
+        // and leave ordinary file name AS IS
+        String fileName = PathUtil.suggestFileName(file.getName(), true, true);
         myNewNameField.setText(fileName);
         final int dotIdx = fileName.lastIndexOf(".");
         if (dotIdx > -1) {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesHandler.java b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesHandler.java
index fa80f33..fcbc320 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesHandler.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesHandler.java
@@ -18,6 +18,7 @@
 import com.intellij.CommonBundle;
 import com.intellij.ide.CopyPasteDelegator;
 import com.intellij.ide.util.EditorHelper;
+import com.intellij.ide.util.PlatformPackageUtil;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.command.CommandProcessor;
 import com.intellij.openapi.project.Project;
@@ -119,11 +120,11 @@
     PsiDirectory targetDirectory;
     if (element instanceof PsiDirectory) {
       targetDirectory = ((PsiDirectory)element).getParentDirectory();
-      assert targetDirectory != null : element;
     }
     else  {
-      targetDirectory = ((PsiFile)element).getContainingDirectory();
+      targetDirectory = PlatformPackageUtil.getDirectory(element);
     }
+    assert targetDirectory != null : element;
 
     PsiElement[] elements = {element};
     CopyFilesOrDirectoriesDialog dialog = new CopyFilesOrDirectoriesDialog(elements, null, element.getProject(), true);
@@ -146,7 +147,7 @@
         directory = directory.getParentDirectory();
       }
       else if (element instanceof PsiFile) {
-        directory = ((PsiFile)element).getContainingDirectory();
+        directory = PlatformPackageUtil.getDirectory(element);
       }
       else {
         throw new IllegalArgumentException("unexpected element " + element);
diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
index 76939d4..0ff4c62 100644
--- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
@@ -127,8 +127,6 @@
 
   @Override
   public void navigateInPreviewEditor(PreviewEditorState editorState) {
-    myEditorState = editorState;
-
     final VirtualFile file = editorState.getFile();
     final LogicalPosition positionToNavigate = editorState.getNavigate();
     final TextAttributes lineAttributes = editorState.getAttributes();
@@ -136,6 +134,7 @@
     Project project = myProject;
 
     clearEditor();
+    myEditorState = editorState;
     remove(myLabel);
     if (document != null) {
       if (getEditor() == null || getEditor().getDocument() != document) {
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/AbstractIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/AbstractIndex.java
index 50e87f8..34b7937 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/AbstractIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/AbstractIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -27,7 +27,7 @@
  */
 public interface AbstractIndex<Key, Value> {
   @NotNull
-  ValueContainer<Value> getData(Key key) throws StorageException;
+  ValueContainer<Value> getData(@NotNull Key key) throws StorageException;
 
-  boolean processAllKeys(Processor<Key> processor, GlobalSearchScope scope, @Nullable IdFilter idFilter) throws StorageException;
+  boolean processAllKeys(@NotNull Processor<Key> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter idFilter) throws StorageException;
 }
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java
index 1648f87..f888981 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -19,6 +19,7 @@
 import com.intellij.openapi.util.Computable;
 import gnu.trove.TIntHashSet;
 import gnu.trove.TIntProcedure;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.Iterator;
@@ -72,11 +73,13 @@
     return getMergedData().size();
   }
 
+  @NotNull
   @Override
   public Iterator<Value> getValueIterator() {
     return getMergedData().getValueIterator();
   }
 
+  @NotNull
   @Override
   public List<Value> toValueList() {
     return getMergedData().toValueList();
@@ -87,11 +90,13 @@
     return getMergedData().isAssociated(value, inputId);
   }
 
+  @NotNull
   @Override
   public IntPredicate getValueAssociationPredicate(Value value) {
     return getMergedData().getValueAssociationPredicate(value);
   }
 
+  @NotNull
   @Override
   public IntIterator getInputIdsIterator(final Value value) {
     return getMergedData().getInputIdsIterator(value);
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/CustomImplementationFileBasedIndexExtension.java b/platform/lang-impl/src/com/intellij/util/indexing/CustomImplementationFileBasedIndexExtension.java
index 32b2227..d504daf 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/CustomImplementationFileBasedIndexExtension.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/CustomImplementationFileBasedIndexExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,6 @@
 
 public abstract class CustomImplementationFileBasedIndexExtension<K, V, I> extends FileBasedIndexExtension<K, V> {
   @NotNull
-  public abstract UpdatableIndex<K, V, I> createIndexImplementation(final ID<K, V> indexId, @NotNull FileBasedIndex owner, @NotNull IndexStorage<K, V> storage)
+  public abstract UpdatableIndex<K, V, I> createIndexImplementation(@NotNull ID<K, V> indexId, @NotNull FileBasedIndex owner, @NotNull IndexStorage<K, V> storage)
     throws StorageException;
 }
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
index ed0dd1b..5785293 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -252,8 +252,8 @@
     myConnection = connection;
   }
 
-  public static boolean isProjectOrWorkspaceFile(final VirtualFile file,
-                                                 final @Nullable FileType fileType) {
+  public static boolean isProjectOrWorkspaceFile(@NotNull VirtualFile file,
+                                                 @Nullable FileType fileType) {
     if (fileType instanceof InternalFileType) return true;
     VirtualFile parent = file.isDirectory() ? file: file.getParent();
     while(parent instanceof VirtualFileSystemEntry) {
@@ -369,8 +369,6 @@
   }
 
   /**
-   * @param extension
-   * @param isCurrentVersionCorrupted
    * @return true if registered index requires full rebuild for some reason, e.g. is just created or corrupted
    */
   private <K, V> boolean registerIndexer(@NotNull final FileBasedIndexExtension<K, V> extension, final boolean isCurrentVersionCorrupted)
@@ -394,7 +392,7 @@
     return versionChanged;
   }
 
-  private <K, V> void initIndexStorage(final FileBasedIndexExtension<K, V> extension, int version, File versionFile)
+  private <K, V> void initIndexStorage(@NotNull FileBasedIndexExtension<K, V> extension, int version, @NotNull File versionFile)
     throws IOException {
     MapIndexStorage<K, V> storage = null;
     final ID<K, V> name = extension.getName();
@@ -429,7 +427,8 @@
               ids.add(name);
             }
           });
-        } else {
+        }
+        else {
           myIndicesWithoutFileTypeInfo.add(name);
         }
 
@@ -545,12 +544,12 @@
                                                                                       @NotNull MemoryIndexStorage<K, ?> storage)
     throws IOException {
     final File indexStorageFile = IndexInfrastructure.getInputIndexStorageFile(indexId);
-    final Ref<Boolean> isBufferingMode = new Ref<Boolean>(false);
+    final AtomicBoolean isBufferingMode = new AtomicBoolean();
     final TIntObjectHashMap<Collection<K>> tempMap = new TIntObjectHashMap<Collection<K>>();
 
     final DataExternalizer<Collection<K>> dataExternalizer = new DataExternalizer<Collection<K>>() {
       @Override
-      public void save(DataOutput out, @NotNull Collection<K> value) throws IOException {
+      public void save(@NotNull DataOutput out, @NotNull Collection<K> value) throws IOException {
         try {
           DataInputOutputUtil.writeINT(out, value.size());
           for (K key : value) {
@@ -564,7 +563,7 @@
 
       @NotNull
       @Override
-      public Collection<K> read(DataInput in) throws IOException {
+      public Collection<K> read(@NotNull DataInput in) throws IOException {
         try {
           final int size = DataInputOutputUtil.readINT(in);
           final List<K> list = new ArrayList<K>(size);
@@ -621,7 +620,7 @@
       }
     };
 
-    storage.addBufferingStateListsner(new MemoryIndexStorage.BufferingStateListener() {
+    storage.addBufferingStateListener(new MemoryIndexStorage.BufferingStateListener() {
       @Override
       public void bufferingStateChanged(boolean newState) {
         synchronized (map) {
@@ -715,10 +714,11 @@
   }
 
   @Override
-  public <K> boolean processAllKeys(@NotNull final ID<K, ?> indexId, Processor<K> processor, @Nullable Project project) {
-    return processAllKeys(indexId, processor, project != null ? GlobalSearchScope.allScope(project) : new EverythingGlobalScope(), null);
+  public <K> boolean processAllKeys(@NotNull final ID<K, ?> indexId, @NotNull Processor<K> processor, @Nullable Project project) {
+    return processAllKeys(indexId, processor, project == null ? new EverythingGlobalScope() : GlobalSearchScope.allScope(project), null);
   }
 
+  @Override
   public <K> boolean processAllKeys(@NotNull ID<K, ?> indexId, @NotNull Processor<K> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter idFilter) {
     try {
       final UpdatableIndex<K, ?, FileContent> index = getIndex(indexId);
@@ -949,7 +949,7 @@
     return null;
   }
 
-  private <K, V> boolean processValuesImpl(@NotNull final ID<K, V> indexId, final K dataKey, final boolean ensureValueProcessedOnce,
+  private <K, V> boolean processValuesImpl(@NotNull final ID<K, V> indexId, @NotNull final K dataKey, final boolean ensureValueProcessedOnce,
                                            @Nullable final VirtualFile restrictToFile, @NotNull final ValueProcessor<V> processor,
                                            @NotNull final GlobalSearchScope scope, @Nullable final IdFilter idFilter) {
     ThrowableConvertor<UpdatableIndex<K, V, FileContent>, Boolean, StorageException> keyProcessor =
@@ -1058,6 +1058,7 @@
       });
     }
 
+    @Override
     public boolean containsFileId(int id) {
       if (id < myMinId) return false;
       if (id > myMaxId) return false;
@@ -1659,7 +1660,7 @@
     return (UpdatableIndex<K, V, FileContent>)pair.getFirst();
   }
 
-  private InputFilter getInputFilter(ID<?, ?> indexId) {
+  private InputFilter getInputFilter(@NotNull ID<?, ?> indexId) {
     final Pair<UpdatableIndex<?, ?, FileContent>, InputFilter> pair = myIndices.get(indexId);
 
     assert pair != null : "Index data is absent for index " + indexId;
@@ -1766,7 +1767,8 @@
     }
   }
 
-  public static FileType getFileType(VirtualFile file) {
+  @NotNull
+  public static FileType getFileType(@NotNull VirtualFile file) {
     FileType fileType = file.getFileType();
     if (fileType == FileTypes.PLAIN_TEXT && FileTypeManagerImpl.isFileTypeDetectedFromContent(file)) {
       fileType = FileTypes.UNKNOWN;
@@ -1803,7 +1805,7 @@
     fc.putUserData(IndexingDataKeys.PROJECT, project);
   }
 
-  private void updateSingleIndex(final ID<?, ?> indexId, @NotNull final VirtualFile file, @Nullable FileContent currentFC)
+  private void updateSingleIndex(@NotNull ID<?, ?> indexId, @NotNull final VirtualFile file, @Nullable FileContent currentFC)
     throws StorageException {
     if (ourRebuildStatus.get(indexId).get() == REQUIRES_REBUILD) {
       return; // the index is scheduled for rebuild, no need to update
@@ -1823,8 +1825,9 @@
     );
   }
 
-  private Runnable createIndexedStampUpdateRunnable(final ID<?, ?> indexId,
-                                                    final VirtualFile file,
+  @NotNull
+  private Runnable createIndexedStampUpdateRunnable(@NotNull final ID<?, ?> indexId,
+                                                    @NotNull final VirtualFile file,
                                                     final boolean hasContent) {
     return new Runnable() {
       @Override
@@ -1843,7 +1846,8 @@
     };
   }
 
-  private Computable<Boolean> createUpdateComputableWithBufferingDisabled(final Computable<Boolean> update) {
+  @NotNull
+  private Computable<Boolean> createUpdateComputableWithBufferingDisabled(@NotNull final Computable<Boolean> update) {
     return new Computable<Boolean>() {
       @Override
       public Boolean compute() {
@@ -2080,7 +2084,7 @@
       });
     }
 
-    private void invalidateIndicesForFile(final VirtualFile file, boolean markForReindex) {
+    private void invalidateIndicesForFile(@NotNull final VirtualFile file, boolean markForReindex) {
       cleanProcessedFlag(file);
       IndexingStamp.flushCache(file);
 
@@ -2439,12 +2443,12 @@
     }
   }
 
-  private boolean shouldIndexFile(final VirtualFile file, final ID<?, ?> indexId) {
+  private boolean shouldIndexFile(@NotNull VirtualFile file, @NotNull ID<?, ?> indexId) {
     return getInputFilter(indexId).acceptInput(file) &&
            (isMock(file) || !isFileIndexed(file, indexId));
   }
 
-  private static boolean isFileIndexed(VirtualFile file, ID<?, ?> indexId) {
+  private static boolean isFileIndexed(VirtualFile file, @NotNull ID<?, ?> indexId) {
     return IndexingStamp.isFileIndexed(file, indexId, IndexInfrastructure.getIndexCreationStamp(indexId));
   }
 
@@ -2537,7 +2541,7 @@
     }
 
     @Override
-    public boolean acceptInput(final VirtualFile file) {
+    public boolean acceptInput(@NotNull final VirtualFile file) {
       return file instanceof VirtualFileWithId && myDelegate.acceptInput(file);
     }
   }
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java
index 7881402..110db72 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -119,14 +119,15 @@
       return myIndex.getNumberOfPendingInvalidations();
     }
 
+    @NotNull
     @Override
-    public VirtualFile[] queryNeededFiles(ProgressIndicator indicator) {
+    public VirtualFile[] queryNeededFiles(@NotNull ProgressIndicator indicator) {
       Collection<VirtualFile> files = myIndex.getFilesToUpdate(myProject);
       return VfsUtilCore.toVirtualFileArray(files);
     }
 
     @Override
-    public void processFile(FileContent fileContent) {
+    public void processFile(@NotNull FileContent fileContent) {
       myIndex.processRefreshedFile(myProject, fileContent);
     }
 
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java
index 6d16833..226542e 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexInfrastructure.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -47,23 +47,28 @@
   private IndexInfrastructure() {
   }
 
+  @NotNull
   public static File getVersionFile(@NotNull ID<?, ?> indexName) {
     return new File(getIndexDirectory(indexName, true), indexName + ".ver");
   }
 
+  @NotNull
   public static File getStorageFile(@NotNull ID<?, ?> indexName) {
     return new File(getIndexRootDir(indexName), indexName.toString());
   }
 
+  @NotNull
   public static File getInputIndexStorageFile(@NotNull ID<?, ?> indexName) {
-    return new File(getIndexRootDir(indexName), indexName.toString()+"_inputs");
+    return new File(getIndexRootDir(indexName), indexName +"_inputs");
   }
 
+  @NotNull
   public static File getIndexRootDir(@NotNull ID<?, ?> indexName) {
     return getIndexDirectory(indexName, false);
   }
 
-  private static File getIndexDirectory(ID<?, ?> indexName, boolean forVersion) {
+  @NotNull
+  private static File getIndexDirectory(@NotNull ID<?, ?> indexName, boolean forVersion) {
     final String dirName = indexName.toString().toLowerCase(Locale.US);
     // store StubIndices under StubUpdating index' root to ensure they are deleted
     // when StubUpdatingIndex version is changed
@@ -76,7 +81,7 @@
 
   private static volatile long ourLastStamp; // ensure any file index stamp increases
 
-  public static synchronized void rewriteVersion(final File file, final int version) throws IOException {
+  public static synchronized void rewriteVersion(@NotNull final File file, final int version) throws IOException {
     final long prevLastModifiedValue = file.lastModified();
     if (file.exists()) {
       FileUtil.delete(file);
@@ -108,7 +113,7 @@
     }
   }
 
-  public static long getIndexCreationStamp(ID<?, ?> indexName) {
+  public static long getIndexCreationStamp(@NotNull ID<?, ?> indexName) {
     Long version = ourIndexIdToCreationStamp.get(indexName);
     if (version != null) return version.longValue();
 
@@ -118,7 +123,7 @@
     return stamp;
   }
 
-  public static boolean versionDiffers(final File versionFile, final int currentIndexVersion) {
+  public static boolean versionDiffers(@NotNull File versionFile, final int currentIndexVersion) {
     try {
       ourLastStamp = Math.max(ourLastStamp, versionFile.lastModified());
       final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(versionFile)));
@@ -137,7 +142,7 @@
   }
 
   @Nullable
-  public static VirtualFile findFileById(final PersistentFS fs, final int id) {
+  public static VirtualFile findFileById(@NotNull PersistentFS fs, final int id) {
     if (ourUnitTestMode) {
       final VirtualFile testFile = findTestFile(id);
       if (testFile != null) {
@@ -159,7 +164,7 @@
   }
 
   @Nullable
-  public static VirtualFile findFileByIdIfCached(final PersistentFS fs, final int id) {
+  public static VirtualFile findFileByIdIfCached(@NotNull PersistentFS fs, final int id) {
     if (ourUnitTestMode) {
       final VirtualFile testFile = findTestFile(id);
       if (testFile != null) {
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexStorage.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexStorage.java
index 0f8bb67..1020876 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/IndexStorage.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -33,15 +33,16 @@
   
   void addValue(Key key, int inputId, Value value) throws StorageException;
 
-  void removeAllValues(Key key, int inputId) throws StorageException;
+  void removeAllValues(@NotNull Key key, int inputId) throws StorageException;
 
   void clear() throws StorageException;
   
   @NotNull
   ValueContainer<Value> read(Key key) throws StorageException;
 
-  boolean processKeys(Processor<Key> processor, GlobalSearchScope scope, @Nullable IdFilter idFilter) throws StorageException;
+  boolean processKeys(@NotNull Processor<Key> processor, GlobalSearchScope scope, @Nullable IdFilter idFilter) throws StorageException;
 
+  @NotNull
   Collection<Key> getKeys() throws StorageException;
 
   void close() throws StorageException;
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
index ebf6906..79a7cb6 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -26,14 +26,19 @@
 import gnu.trove.TObjectLongHashMap;
 import gnu.trove.TObjectLongProcedure;
 import gnu.trove.TObjectProcedure;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.List;
 import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentMap;
 
 /**
  * @author Eugene Zhuravlev
@@ -100,16 +105,17 @@
             }
           }
         });
-      } else {
+      }
+      else {
         DataInputOutputUtil.writeTIME(stream, DataInputOutputUtil.timeBase);
       }
     }
 
-    public long get(ID<?, ?> id) {
+    private long get(ID<?, ?> id) {
       return myIndexStamps != null? myIndexStamps.get(id) : 0L;
     }
 
-    public void set(ID<?, ?> id, long tmst) {
+    private void set(ID<?, ?> id, long tmst) {
       try {
         if (tmst < 0) {
           if (myIndexStamps == null) return;
@@ -130,9 +136,8 @@
     }
   }
 
-  private static final ConcurrentHashMap<VirtualFile, Timestamps> myTimestampsCache = new ConcurrentHashMap<VirtualFile, Timestamps>();
-  private static final int CAPACITY = 100;
-  private static final ArrayBlockingQueue<VirtualFile> myFinishedFiles = new ArrayBlockingQueue<VirtualFile>(CAPACITY);
+  private static final ConcurrentMap<VirtualFile, Timestamps> myTimestampsCache = new ConcurrentHashMap<VirtualFile, Timestamps>();
+  private static final BlockingQueue<VirtualFile> ourFinishedFiles = new ArrayBlockingQueue<VirtualFile>(100);
 
   public static boolean isFileIndexed(VirtualFile file, ID<?, ?> indexName, final long indexCreationStamp) {
     try {
@@ -148,7 +153,7 @@
     return false;
   }
 
-  public static long getIndexStamp(VirtualFile file, ID<?, ?> indexName) {
+  public static long getIndexStamp(@NotNull VirtualFile file, ID<?, ?> indexName) {
     synchronized (getStripedLock(file)) {
       Timestamps stamp = createOrGetTimeStamp(file);
       if (stamp != null) return stamp.get(indexName);
@@ -156,7 +161,7 @@
     }
   }
 
-  private static Timestamps createOrGetTimeStamp(VirtualFile file) {
+  private static Timestamps createOrGetTimeStamp(@NotNull VirtualFile file) {
     if (file instanceof NewVirtualFile && file.isValid()) {
       Timestamps timestamps = myTimestampsCache.get(file);
       if (timestamps == null) {
@@ -174,7 +179,7 @@
     return null;
   }
 
-  public static void update(final VirtualFile file, final ID<?, ?> indexName, final long indexCreationStamp) {
+  public static void update(@NotNull VirtualFile file, @NotNull ID<?, ?> indexName, final long indexCreationStamp) {
     synchronized (getStripedLock(file)) {
       try {
         Timestamps stamp = createOrGetTimeStamp(file);
@@ -185,7 +190,7 @@
     }
   }
 
-  public static void removeAllIndexedState(VirtualFile file) {
+  public static void removeAllIndexedState(@NotNull VirtualFile file) {
     synchronized (getStripedLock(file)) {
       if (file instanceof NewVirtualFile && file.isValid()) {
         myTimestampsCache.put(file, new Timestamps());
@@ -193,7 +198,8 @@
     }
   }
 
-  public static Collection<ID<?,?>> getIndexedIds(final VirtualFile file) {
+  @NotNull
+  public static Collection<ID<?,?>> getIndexedIds(@NotNull VirtualFile file) {
     synchronized (getStripedLock(file)) {
       try {
         Timestamps stamp = createOrGetTimeStamp(file);
@@ -220,17 +226,11 @@
   }
 
   public static void flushCache(@Nullable VirtualFile finishedFile) {
-    if (finishedFile == null || !myFinishedFiles.offer(finishedFile)) {
-      VirtualFile[] files = null;
-      synchronized (myFinishedFiles) {
-        int size = myFinishedFiles.size();
-        if ((finishedFile == null && size > 0) || size == CAPACITY) {
-          files = myFinishedFiles.toArray(new VirtualFile[size]);
-          myFinishedFiles.clear();
-        }
-      }
+    if (finishedFile == null || !ourFinishedFiles.offer(finishedFile)) {
+      List<VirtualFile> files = new ArrayList<VirtualFile>(ourFinishedFiles.size());
+      ourFinishedFiles.drainTo(files);
 
-      if (files != null) {
+      if (!files.isEmpty()) {
         for(VirtualFile file:files) {
           synchronized (getStripedLock(file)) {
             Timestamps timestamp = myTimestampsCache.remove(file);
@@ -248,7 +248,7 @@
           }
         }
       }
-      if (finishedFile != null) myFinishedFiles.offer(finishedFile);
+      if (finishedFile != null) ourFinishedFiles.offer(finishedFile);
     }
   }
 
@@ -257,7 +257,7 @@
     for(int i = 0; i < ourLocks.length; ++i) ourLocks[i] = new Object();
   }
 
-  private static Object getStripedLock(VirtualFile file) {
+  private static Object getStripedLock(@NotNull VirtualFile file) {
     if (!(file instanceof NewVirtualFile)) return 0;
     int id = ((NewVirtualFile)file).getId();
     return ourLocks[(id & 0xFF) % ourLocks.length];
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java b/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java
index 649bd25..bbd0155 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MapIndexStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@
 
   private final Lock l = new ReentrantLock();
   private final DataExternalizer<Value> myDataExternalizer;
-  private boolean myHighKeySelectivity;
+  private final boolean myHighKeySelectivity;
   private final LowMemoryWatcher myLowMemoryFlusher = LowMemoryWatcher.register(new Runnable() {
     @Override
     public void run() {
@@ -70,7 +70,8 @@
           myCache.clear();
           if (myMap.isDirty()) myMap.force();
         }
-      } finally {
+      }
+      finally {
         l.unlock();
       }
     }
@@ -89,9 +90,7 @@
                          @NotNull DataExternalizer<Value> valueExternalizer,
                          final int cacheSize,
                          boolean highKeySelectivity,
-                         boolean buildKeyHashToVirtualFileMapping
-                         ) throws IOException {
-
+                         boolean buildKeyHashToVirtualFileMapping) throws IOException {
     myStorageFile = storageFile;
     myKeyDescriptor = keyDescriptor;
     myCacheSize = cacheSize;
@@ -150,6 +149,7 @@
     myKeyHashToVirtualFileMapping = myBuildKeyHashToVirtualFileMapping ? new KeyHash2VirtualFileEnumerator(getProjectFile()) : null;
   }
 
+  @NotNull
   private File getProjectFile() {
     return new File(myStorageFile.getPath() + ".project");
   }
@@ -222,7 +222,7 @@
   }
 
   @Override
-  public boolean processKeys(final Processor<Key> processor, GlobalSearchScope scope, final IdFilter idFilter) throws StorageException {
+  public boolean processKeys(@NotNull final Processor<Key> processor, GlobalSearchScope scope, final IdFilter idFilter) throws StorageException {
     l.lock();
     try {
       myCache.clear(); // this will ensure that all new keys are made into the map
@@ -298,7 +298,8 @@
     }
   }
 
-  private static TIntHashSet loadHashedIds(File fileWithCaches) throws IOException {
+  @NotNull
+  private static TIntHashSet loadHashedIds(@NotNull File fileWithCaches) throws IOException {
     DataInputStream inputStream = null;
     try {
       inputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(fileWithCaches)));
@@ -315,12 +316,13 @@
       if (inputStream != null) {
         try {
           inputStream.close();
-        } catch (IOException ex) {}
+        }
+        catch (IOException ignored) {}
       }
     }
   }
 
-  private void saveHashedIds(TIntHashSet hashMaskSet, int largestId, GlobalSearchScope scope) {
+  private void saveHashedIds(@NotNull TIntHashSet hashMaskSet, int largestId, @NotNull GlobalSearchScope scope) {
     File newFileWithCaches = getSavedProjectFileValueIds(largestId, scope);
     assert newFileWithCaches != null;
     DataOutputStream stream = null;
@@ -341,17 +343,22 @@
         }
       });
       if (result) myLastScannedId = largestId;
-    } catch (IOException ex) {}
+    }
+    catch (IOException ignored) {
+
+    }
     finally {
       if (stream != null) {
         try {
           stream.close();
-        } catch (IOException ex) {}
+        }
+        catch (IOException ignored) {}
       }
     }
   }
 
-  private @Nullable File getSavedProjectFileValueIds(int id, GlobalSearchScope scope) {
+  @Nullable
+  private File getSavedProjectFileValueIds(int id, @NotNull GlobalSearchScope scope) {
     Project project = scope.getProject();
     if (project == null) return null;
     return new File(myStorageFile.getPath() + ".project."+project.hashCode() + "."+id + "." + scope.isSearchInLibraries());
@@ -423,7 +430,7 @@
   }
 
   @Override
-  public void removeAllValues(Key key, int inputId) throws StorageException {
+  public void removeAllValues(@NotNull Key key, int inputId) throws StorageException {
     try {
       myMap.markDirty();
       // important: assuming the key exists in the index
@@ -436,13 +443,13 @@
 
   private static class IntPairInArrayKeyDescriptor implements KeyDescriptor<int[]>, DifferentSerializableBytesImplyNonEqualityPolicy {
     @Override
-    public void save(DataOutput out, int[] value) throws IOException {
+    public void save(@NotNull DataOutput out, int[] value) throws IOException {
       DataInputOutputUtil.writeINT(out, value[0]);
       DataInputOutputUtil.writeINT(out, value[1]);
     }
 
     @Override
-    public int[] read(DataInput in) throws IOException {
+    public int[] read(@NotNull DataInput in) throws IOException {
       return new int[] {DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in)};
     }
 
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
index f49f70d..a19e2d9 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -20,6 +20,7 @@
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.Factory;
+import com.intellij.openapi.util.NotNullComputable;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.psi.search.GlobalSearchScope;
@@ -33,8 +34,10 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.Callable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -146,18 +149,20 @@
     }
   }
 
+  @NotNull
   @Override
   public final Lock getReadLock() {
     return myLock.readLock();
   }
 
+  @NotNull
   @Override
   public final Lock getWriteLock() {
     return myLock.writeLock();
   }
 
   @Override
-  public boolean processAllKeys(Processor<Key> processor, GlobalSearchScope scope, IdFilter idFilter) throws StorageException {
+  public boolean processAllKeys(@NotNull Processor<Key> processor, @NotNull GlobalSearchScope scope, IdFilter idFilter) throws StorageException {
     final Lock lock = getReadLock();
     try {
       lock.lock();
@@ -170,7 +175,7 @@
 
   @Override
   @NotNull
-  public ValueContainer<Value> getData(final Key key) throws StorageException {
+  public ValueContainer<Value> getData(@NotNull final Key key) throws StorageException {
     final Lock lock = getReadLock();
     try {
       lock.lock();
@@ -203,6 +208,7 @@
     return null;
   }
 
+  @NotNull
   @Override
   public final Computable<Boolean> update(final int inputId, @Nullable final Input content) {
 
@@ -219,17 +225,24 @@
           @Override
           public void run() {
             try {
-              updateWithMap(inputId, data, new Callable<Collection<Key>>() {
+              updateWithMap(inputId, data, new NotNullComputable<Collection<Key>>() {
+                @NotNull
                 @Override
-                public Collection<Key> call() throws Exception {
+                public Collection<Key> compute() {
                   if (myInputsIndex == null) {
                     return new SmartList<Key>((Key)(Integer)inputId);
                   }
-                  final Collection<Key> oldKeys = myInputsIndex.get(inputId);
-                  return oldKeys == null? Collections.<Key>emptyList() : oldKeys;
+                  try {
+                    Collection<Key> oldKeys = myInputsIndex.get(inputId);
+                    return oldKeys == null? Collections.<Key>emptyList() : oldKeys;
+                  }
+                  catch (IOException e) {
+                    throw new RuntimeException(e);
+                  }
                 }
               });
-            } catch (StorageException ex) {
+            }
+            catch (StorageException ex) {
               exRef.set(ex);
             }
           }
@@ -239,20 +252,19 @@
           LOG.info(exRef.get());
           FileBasedIndex.getInstance().requestRebuild(myIndexId);
           return Boolean.FALSE;
-        } else {
-          return Boolean.TRUE;
         }
+        return Boolean.TRUE;
       }
     };
   }
 
   protected void updateWithMap(final int inputId,
                                @NotNull Map<Key, Value> newData,
-                               @NotNull Callable<Collection<Key>> oldKeysGetter) throws StorageException {
+                               @NotNull NotNullComputable<Collection<Key>> oldKeysGetter) throws StorageException {
     getWriteLock().lock();
     try {
       try {
-        for (Key key : oldKeysGetter.call()) {
+        for (Key key : oldKeysGetter.compute()) {
           myStorage.removeAllValues(key, inputId);
         }
       }
@@ -277,7 +289,8 @@
           }
         });
         if (!b) throw exceptionRef.get();
-      } else {
+      }
+      else {
         for (Map.Entry<Key, Value> entry : newData.entrySet()) {
           myStorage.addValue(entry.getKey(), inputId, entry.getValue());
         }
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java b/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java
index 3ef7d2a..2ae474b 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -34,6 +34,7 @@
  */
 public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value> {
   private final Map<Key, ChangeTrackingValueContainer<Value>> myMap = new HashMap<Key, ChangeTrackingValueContainer<Value>>();
+  @NotNull
   private final IndexStorage<Key, Value> myBackendStorage;
   private final List<BufferingStateListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
   private final AtomicBoolean myBufferingEnabled = new AtomicBoolean(false);
@@ -44,19 +45,20 @@
     void memoryStorageCleared();
   }
 
-  public MemoryIndexStorage(IndexStorage<Key, Value> backend) {
+  public MemoryIndexStorage(@NotNull IndexStorage<Key, Value> backend) {
     myBackendStorage = backend;
   }
 
+  @NotNull
   public IndexStorage<Key, Value> getBackendStorage() {
     return myBackendStorage;
   }
 
-  public void addBufferingStateListsner(BufferingStateListener listener) {
+  public void addBufferingStateListener(@NotNull BufferingStateListener listener) {
     myListeners.add(listener);
   }
 
-  public void removeBufferingStateListsner(BufferingStateListener listener) {
+  public void removeBufferingStateListener(@NotNull BufferingStateListener listener) {
     myListeners.remove(listener);
   }
 
@@ -99,6 +101,7 @@
     myBackendStorage.flush();
   }
 
+  @NotNull
   @Override
   public Collection<Key> getKeys() throws StorageException {
     final Set<Key> keys = new HashSet<Key>();
@@ -107,7 +110,7 @@
   }
 
   @Override
-  public boolean processKeys(final Processor<Key> processor, GlobalSearchScope scope, IdFilter idFilter) throws StorageException {
+  public boolean processKeys(@NotNull final Processor<Key> processor, GlobalSearchScope scope, IdFilter idFilter) throws StorageException {
     final Set<Key> stopList = new HashSet<Key>();
 
     Processor<Key> decoratingProcessor = new Processor<Key>() {
@@ -129,7 +132,7 @@
       }
       stopList.add(key);
     }
-    return myBackendStorage.processKeys(stopList.size() == 0 && myMap.size() == 0 ? processor : decoratingProcessor, scope, idFilter);
+    return myBackendStorage.processKeys(stopList.isEmpty() && myMap.isEmpty() ? processor : decoratingProcessor, scope, idFilter);
   }
 
   @Override
@@ -147,7 +150,7 @@
   }
 
   @Override
-  public void removeAllValues(Key key, int inputId) throws StorageException {
+  public void removeAllValues(@NotNull Key key, int inputId) throws StorageException {
     if (myBufferingEnabled.get()) {
       getMemValueContainer(key).removeAssociatedValue(inputId);
       return;
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java b/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java
index 2a18906..a4975f1 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
 import com.intellij.openapi.roots.CollectingContentIterator;
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -49,8 +50,9 @@
     return myIndex.getNumberOfPendingInvalidations();
   }
 
+  @NotNull
   @Override
-  public VirtualFile[] queryNeededFiles(ProgressIndicator indicator) {
+  public VirtualFile[] queryNeededFiles(@NotNull ProgressIndicator indicator) {
     myIndex.filesUpdateStarted(myProject);
     CollectingContentIterator finder = myIndex.createContentIterator(indicator);
     long l = System.currentTimeMillis();
@@ -66,10 +68,11 @@
   }
 
   @Override
-  public void processFile(final FileContent fileContent) {
+  public void processFile(@NotNull FileContent fileContent) {
     try {
       myIndex.indexFileContent(myProject, fileContent);
-    } finally {
+    }
+    finally {
       IndexingStamp.flushCache(fileContent.getVirtualFile());
     }
   }
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/UpdatableIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/UpdatableIndex.java
index 589db0f..4b431ed 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/UpdatableIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/UpdatableIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 package com.intellij.util.indexing;
 
 import com.intellij.openapi.util.Computable;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.concurrent.locks.Lock;
@@ -31,12 +32,13 @@
 
   void flush() throws StorageException;
 
-  /**
-   */
+  @NotNull
   Computable<Boolean> update(int inputId, @Nullable Input content);
-  
+
+  @NotNull
   Lock getReadLock();
-  
+
+  @NotNull
   Lock getWriteLock();
   
   void dispose();
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java
index d901751..47efe30 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -16,6 +16,8 @@
 
 package com.intellij.util.indexing;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.util.Iterator;
 import java.util.List;
 
@@ -35,15 +37,19 @@
   abstract static class IntPredicate {
     abstract boolean contains(int id);
   }
-  
+
+  @NotNull
   public abstract IntIterator getInputIdsIterator(Value value);
 
   public abstract boolean isAssociated(Value value, int inputId);
 
+  @NotNull
   public abstract IntPredicate getValueAssociationPredicate(Value value);
 
+  @NotNull
   public abstract Iterator<Value> getValueIterator();
 
+  @NotNull
   public abstract List<Value> toValueList();
 
   public abstract int size();
@@ -53,7 +59,7 @@
     boolean perform(int id, T value);
   }
 
-  public final boolean forEach(final ContainerAction<Value> action) {
+  public final boolean forEach(@NotNull ContainerAction<Value> action) {
     for (final Iterator<Value> valueIterator = getValueIterator(); valueIterator.hasNext();) {
       final Value value = valueIterator.next();
       for (final IntIterator intIterator = getInputIdsIterator(value); intIterator.hasNext();) {
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java
index ae9424d..ddc5381 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -21,6 +21,7 @@
 import com.intellij.util.SmartList;
 import com.intellij.util.containers.EmptyIterator;
 import gnu.trove.*;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.*;
 
@@ -139,6 +140,7 @@
     return true;
   }
 
+  @NotNull
   @Override
   public Iterator<Value> getValueIterator() {
     if (myInputIdMapping != null) {
@@ -190,6 +192,7 @@
     }
   }
 
+  @NotNull
   @Override
   public List<Value> toValueList() {
     if (myInputIdMapping == null) {
@@ -216,6 +219,7 @@
     return false;
   }
 
+  @NotNull
   @Override
   public IntPredicate getValueAssociationPredicate(Value value) {
     final Object input = getInput(value);
@@ -247,6 +251,7 @@
     };
   }
 
+  @NotNull
   @Override
   public IntIterator getInputIdsIterator(Value value) {
     final Object input = getInput(value);
@@ -335,6 +340,7 @@
     }
   };
 
+  @NotNull
   public ValueContainerImpl<Value> copy() {
     ValueContainerImpl<Value> container = new ValueContainerImpl<Value>();
 
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java
index c4385b4..3bf0ece 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerMap.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.util.indexing;
 
 import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
@@ -71,7 +86,7 @@
     }
 
     @Override
-    public void save(final DataOutput out, @NotNull final ValueContainer<T> container) throws IOException {
+    public void save(@NotNull final DataOutput out, @NotNull final ValueContainer<T> container) throws IOException {
       saveImpl(out, container);
     }
 
@@ -79,29 +94,24 @@
       DataInputOutputUtil.writeSINT(out, -inputId);
     }
 
-    private void saveImpl(final DataOutput out, @NotNull final ValueContainer<T> container) throws IOException {
+    private void saveImpl(@NotNull DataOutput out, @NotNull final ValueContainer<T> container) throws IOException {
       DataInputOutputUtil.writeSINT(out, container.size());
       for (final Iterator<T> valueIterator = container.getValueIterator(); valueIterator.hasNext();) {
         final T value = valueIterator.next();
         myExternalizer.save(out, value);
 
         final ValueContainer.IntIterator ids = container.getInputIdsIterator(value);
-        if (ids != null) {
-          DataInputOutputUtil.writeSINT(out, ids.size());
-          while (ids.hasNext()) {
-            final int id = ids.next();
-            DataInputOutputUtil.writeSINT(out, id);
-          }
-        }
-        else {
-          DataInputOutputUtil.writeSINT(out, 0);
+        DataInputOutputUtil.writeSINT(out, ids.size());
+        while (ids.hasNext()) {
+          final int id = ids.next();
+          DataInputOutputUtil.writeSINT(out, id);
         }
       }
     }
 
     @NotNull
     @Override
-    public ValueContainerImpl<T> read(final DataInput in) throws IOException {
+    public ValueContainerImpl<T> read(@NotNull final DataInput in) throws IOException {
       DataInputStream stream = (DataInputStream)in;
       final ValueContainerImpl<T> valueContainer = new ValueContainerImpl<T>();
 
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java b/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java
index f394c83..6dd7aeb 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java
@@ -2,6 +2,7 @@
 
 import com.google.common.collect.Lists;
 import com.intellij.icons.AllIcons;
+import com.intellij.ide.ActivityTracker;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.application.Application;
 import com.intellij.openapi.application.ApplicationManager;
@@ -397,6 +398,9 @@
     myPackagesTable.setPaintBusy(false);
     myPackagesTable.getEmptyText().setText(StatusText.DEFAULT_EMPTY_TEXT);
     updateUninstallUpgrade();
+    // Action button presentations won't be updated if no events occur (e.g. mouse isn't moving, keys aren't being pressed).
+    // In that case emulating activity will help:
+    ActivityTracker.getInstance().inc();
   }
 
   public void doUpdatePackages(@NotNull final PackageManagementService packageManagementService) {
diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java b/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java
index 3c30750..24a7603 100644
--- a/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java
+++ b/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java
@@ -30,7 +30,10 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.project.ProjectManager;
 import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.Clock;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.*;
 import com.intellij.openapi.vfs.encoding.EncodingRegistry;
diff --git a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java
index a42a1bf..445ac01 100644
--- a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java
+++ b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java
@@ -240,7 +240,7 @@
       commands = CommandLineUtil.toCommandLine(myExePath, myProgramParams.getList());
     }
     catch (ExecutionException e) {
-      LOG.warn(e);
+      LOG.info(e);
       throw e;
     }
 
@@ -248,7 +248,7 @@
       return startProcess(commands);
     }
     catch (IOException e) {
-      LOG.warn(e);
+      LOG.info(e);
       throw new ProcessNotCreatedException(e.getMessage(), e, this);
     }
   }
diff --git a/platform/platform-api/src/com/intellij/ide/caches/CacheUpdater.java b/platform/platform-api/src/com/intellij/ide/caches/CacheUpdater.java
index 219f23b..3599242 100644
--- a/platform/platform-api/src/com/intellij/ide/caches/CacheUpdater.java
+++ b/platform/platform-api/src/com/intellij/ide/caches/CacheUpdater.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -18,13 +18,15 @@
 
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
 
 public interface CacheUpdater {
   int getNumberOfPendingUpdateJobs();
 
-  VirtualFile[] queryNeededFiles(ProgressIndicator indicator);
+  @NotNull
+  VirtualFile[] queryNeededFiles(@NotNull ProgressIndicator indicator);
 
-  void processFile(FileContent fileContent);
+  void processFile(@NotNull FileContent fileContent);
 
   void updatingDone();
 
diff --git a/platform/platform-api/src/com/intellij/lang/LanguageDialect.java b/platform/platform-api/src/com/intellij/lang/LanguageDialect.java
index 532d4d8..f5bc6b2 100644
--- a/platform/platform-api/src/com/intellij/lang/LanguageDialect.java
+++ b/platform/platform-api/src/com/intellij/lang/LanguageDialect.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -18,6 +18,8 @@
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
+/** @deprecated use {@linkplain Language#Language(Language, String, String...)} (to remove in IDEA 15) */
+@SuppressWarnings("UnusedDeclaration")
 public abstract class LanguageDialect extends Language {
   public LanguageDialect(@NonNls @NotNull String id, @NotNull Language baseLanguage) {
     super(baseLanguage, id, "");
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/EmptyAction.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/EmptyAction.java
index 4ae67c9..9e53c35 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/EmptyAction.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/EmptyAction.java
@@ -15,11 +15,11 @@
  */
 package com.intellij.openapi.actionSystem;
 
+import com.intellij.openapi.actionSystem.ex.ActionUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import java.util.ArrayList;
 
 /**
  * This class purpose is to reserve action-id in a plugin.xml so the action appears in Keymap.
@@ -74,13 +74,8 @@
   }
 
   public static void registerActionShortcuts(JComponent component, final JComponent fromComponent) {
-    @SuppressWarnings("unchecked")
-    final ArrayList<AnAction> actionList =
-    (ArrayList<AnAction>)fromComponent.getClientProperty(ourClientProperty);
-    if (actionList != null) {
-      for (AnAction anAction : actionList) {
-        anAction.registerCustomShortcutSet(anAction.getShortcutSet(), component);
-      }
+    for (AnAction anAction : ActionUtil.getActions(fromComponent)) {
+      anAction.registerCustomShortcutSet(anAction.getShortcutSet(), component);
     }
   }
 
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
index b515b84..2004b55 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
@@ -115,7 +115,8 @@
   @NonNls String ACTION_FIND_NEXT = "FindNext";
   @NonNls String ACTION_FIND_PREVIOUS = "FindPrevious";
   @NonNls String ACTION_SELECT_NEXT_OCCURENCE = "SelectNextOccurrence";
-  @NonNls String ACTION_UNSELECT_LAST_OCCURENCE = "UnselectLastOccurrence";
+  @NonNls String ACTION_SELECT_ALL_OCCURRENCES = "SelectAllOccurrences";
+  @NonNls String ACTION_UNSELECT_PREVIOUS_OCCURENCE = "UnselectPreviousOccurrence";
   @NonNls String ACTION_COMPILE = "Compile";
   @NonNls String ACTION_COMPILE_PROJECT = "CompileProject";
   @NonNls String ACTION_MAKE_MODULE = "MakeModule";
@@ -189,6 +190,8 @@
   @NonNls String GROUP_OTHER_MENU = "OtherMenu";
   @NonNls String GROUP_EDITOR = "EditorActions";
   @NonNls String GROUP_DEBUGGER = "DebuggerActions";
+  
+  @NonNls String ACTION_TOGGLE_LINE_BREAKPOINT = "ToggleLineBreakpoint";
 
   @NonNls String ACTION_REFRESH = "Refresh";
 
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java
index 8132f9e..e0dc548 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionUtil.java
@@ -27,7 +27,9 @@
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 
+import javax.swing.*;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 public class ActionUtil {
@@ -166,5 +168,10 @@
     }
   }
 
-
+  @NotNull
+  public static List<AnAction> getActions(@NotNull JComponent component) {
+    Object property = component.getClientProperty(AnAction.ourClientProperty);
+    //noinspection unchecked
+    return property == null ? Collections.<AnAction>emptyList() : (List<AnAction>)property;
+  }
 }
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/SimpleContent.java b/platform/platform-api/src/com/intellij/openapi/diff/SimpleContent.java
index 55960fb..9a0af4a 100644
--- a/platform/platform-api/src/com/intellij/openapi/diff/SimpleContent.java
+++ b/platform/platform-api/src/com/intellij/openapi/diff/SimpleContent.java
@@ -16,6 +16,7 @@
 package com.intellij.openapi.diff;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.EditorFactory;
 import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -29,8 +30,8 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.io.*;
-import java.nio.charset.Charset;
 import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
 
 /**
  * Allows to compare some text not associated with file or document.
@@ -210,16 +211,18 @@
   private static class LineSeparators {
     private String mySeparator;
 
-    public String correctText(String text) {
-      LineTokenizer lineTokenizer = new LineTokenizer(text);
-      String[] lines = lineTokenizer.execute();
+    @NotNull
+    public String correctText(@NotNull String text) {
+      DiffString.LineTokenizer lineTokenizer = new DiffString.LineTokenizer(DiffString.create(text));
+      DiffString[] lines = lineTokenizer.execute();
       mySeparator = lineTokenizer.getLineSeparator();
       LOG.assertTrue(mySeparator == null || !mySeparator.isEmpty());
       if (mySeparator == null) mySeparator = SystemProperties.getLineSeparator();
-      return LineTokenizer.concatLines(lines);
+      return DiffString.concatenate(lines).toString();
     }
 
-    public String restoreText(String text) {
+    @NotNull
+    public String restoreText(@NotNull String text) {
       if (mySeparator == null) throw new NullPointerException();
       return text.replaceAll("\n", mySeparator);
     }
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
index cf674d6..8058f6c 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
@@ -25,6 +25,7 @@
 import com.intellij.openapi.util.text.LineTokenizer;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.util.Producer;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.awt.datatransfer.DataFlavor;
@@ -45,12 +46,27 @@
     int selectionStart = selectionModel.getSelectionStart();
     int selectionEnd = selectionModel.getSelectionEnd();
 
-    editor.getCaretModel().moveToOffset(selectionStart);
+    VisualPosition selectionStartPosition = selectionModel.getSelectionStartPosition();
+    if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets() && selectionStartPosition != null) {
+      editor.getCaretModel().moveToVisualPosition(selectionStartPosition);
+    }
+    else {
+      editor.getCaretModel().moveToOffset(selectionStart);
+    }
     selectionModel.removeSelection();
     editor.getDocument().deleteString(selectionStart, selectionEnd);
     editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
   }
 
+  public static void deleteSelectedTextForAllCarets(@NotNull final Editor editor) {
+    editor.getCaretModel().runForEachCaret(new CaretAction() {
+      @Override
+      public void perform(Caret caret) {
+        deleteSelectedText(editor);
+      }
+    });
+  }
+
   public static void deleteBlockSelection(Editor editor) {
     SelectionModel selectionModel = editor.getSelectionModel();
     if (!selectionModel.hasBlockSelection()) return;
@@ -81,14 +97,24 @@
     editor.getSelectionModel().setBlockSelection(new LogicalPosition(startLine, caretColumn), new LogicalPosition(endLine, caretColumn));
   }
 
-  public static void insertStringAtCaret(Editor editor, String s) {
+  public static void insertStringAtCaret(Editor editor, @NotNull String s) {
     insertStringAtCaret(editor, s, false, true);
   }
 
-  public static int insertStringAtCaret(Editor editor, String s, boolean toProcessOverwriteMode, boolean toMoveCaret) {
+  public static int insertStringAtCaret(Editor editor, @NotNull String s, boolean toProcessOverwriteMode, boolean toMoveCaret) {
+    return insertStringAtCaret(editor, s, toProcessOverwriteMode, toMoveCaret, s.length());
+  }
+
+  public static int insertStringAtCaret(Editor editor, @NotNull String s, boolean toProcessOverwriteMode, boolean toMoveCaret, int caretShift) {
     final SelectionModel selectionModel = editor.getSelectionModel();
     if (selectionModel.hasSelection()) {
-      editor.getCaretModel().moveToOffset(selectionModel.getSelectionStart(), true);
+      VisualPosition startPosition = selectionModel.getSelectionStartPosition();
+      if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets() && startPosition != null) {
+        editor.getCaretModel().moveToVisualPosition(startPosition);
+      }
+      else {
+        editor.getCaretModel().moveToOffset(selectionModel.getSelectionStart(), true);
+      }
     }
 
     // There is a possible case that particular soft wraps become hard wraps if the caret is located at soft wrap-introduced virtual
@@ -120,7 +146,7 @@
       document.replaceString(oldOffset, Math.min(endOffset, oldOffset + s.length()), s);
     }
 
-    int offset = oldOffset + s.length();
+    int offset = oldOffset + filler.length() + caretShift;
     if (toMoveCaret){
       editor.getCaretModel().moveToOffset(offset, true);
       editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
@@ -139,7 +165,7 @@
     if (text == null) return null;
 
     if (editor.getCaretModel().supportsMultipleCarets()) {
-      int caretCount = editor.getCaretModel().getAllCarets().size();
+      int caretCount = editor.getCaretModel().getCaretCount();
       final Iterator<String> segments = new ClipboardTextPerCaretSplitter().split(text, caretCount).iterator();
       editor.getCaretModel().runForEachCaret(new CaretAction() {
         @Override
@@ -365,6 +391,62 @@
     }
   }
 
+  public static void typeInStringAtCaretHonorMultipleCarets(final Editor editor, @NotNull final String str, final boolean toProcessOverwriteMode) {
+    typeInStringAtCaretHonorMultipleCarets(editor, str, toProcessOverwriteMode, str.length());
+  }
+
+  /**
+   * Inserts given string at each caret's position. Effective caret shift will be equal to <code>caretShift</code> for each caret.
+   */
+  public static void typeInStringAtCaretHonorMultipleCarets(final Editor editor, @NotNull final String str, final boolean toProcessOverwriteMode, final int caretShift)
+    throws ReadOnlyFragmentModificationException
+  {
+    Document doc = editor.getDocument();
+    final SelectionModel selectionModel = editor.getSelectionModel();
+    if (selectionModel.hasBlockSelection()) {
+      RangeMarker guard = selectionModel.getBlockSelectionGuard();
+      if (guard != null) {
+        DocumentEvent evt = new MockDocumentEvent(doc, editor.getCaretModel().getOffset());
+        ReadOnlyFragmentModificationException e = new ReadOnlyFragmentModificationException(evt, guard);
+        EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e);
+      }
+      else {
+        final LogicalPosition start = selectionModel.getBlockStart();
+        final LogicalPosition end = selectionModel.getBlockEnd();
+        assert start != null;
+        assert end != null;
+
+        int column = Math.min(start.column, end.column);
+        int startLine = Math.min(start.line, end.line);
+        int endLine = Math.max(start.line, end.line);
+        deleteBlockSelection(editor);
+        for (int i = startLine; i <= endLine; i++) {
+          editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(i, column));
+          insertStringAtCaret(editor, str, toProcessOverwriteMode, true, caretShift);
+        }
+        selectionModel.setBlockSelection(new LogicalPosition(startLine, column + str.length()),
+                                         new LogicalPosition(endLine, column + str.length()));
+      }
+    }
+    else {
+      editor.getCaretModel().runForEachCaret(new CaretAction() {
+        @Override
+        public void perform(Caret caret) {
+          insertStringAtCaret(editor, str, toProcessOverwriteMode, true, caretShift);
+        }
+      });
+    }
+  }
+
+  public static void moveAllCaretsRelatively(@NotNull Editor editor, final int caretShift) {
+    editor.getCaretModel().runForEachCaret(new CaretAction() {
+      @Override
+      public void perform(Caret caret) {
+        caret.moveToOffset(caret.getOffset() + caretShift);
+      }
+    });
+  }
+
   /** @deprecated use {@link #pasteTransferable(Editor, Producer)} (to remove in IDEA 14) */
   @SuppressWarnings("UnusedDeclaration")
   public static TextRange pasteFromClipboard(Editor editor) {
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java
index 0c468aa..f296c64 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java
@@ -17,7 +17,7 @@
 
 import com.intellij.codeStyle.CodeStyleFacade;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.editor.event.DocumentAdapter;
 import com.intellij.openapi.editor.event.DocumentEvent;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -36,11 +36,13 @@
 import java.util.List;
 import java.util.concurrent.ConcurrentMap;
 
-public class LazyRangeMarkerFactory extends AbstractProjectComponent {
+public class LazyRangeMarkerFactory {
+  private final Project myProject;
   private final ConcurrentMap<VirtualFile,WeakList<LazyMarker>> myMarkers = new ConcurrentWeakHashMap<VirtualFile, WeakList<LazyMarker>>();
 
   public LazyRangeMarkerFactory(@NotNull Project project, @NotNull final FileDocumentManager fileDocumentManager) {
-    super(project);
+    myProject = project;
+
     EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() {
       @Override
       public void beforeDocumentChange(DocumentEvent e) {
@@ -71,7 +73,7 @@
   }
 
   public static LazyRangeMarkerFactory getInstance(Project project) {
-    return project.getComponent(LazyRangeMarkerFactory.class);
+    return ServiceManager.getService(project, LazyRangeMarkerFactory.class);
   }
 
   @NotNull
@@ -92,8 +94,7 @@
     return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
       @Override
       public RangeMarker compute() {
-        FileDocumentManager fdm = FileDocumentManager.getInstance();
-        final Document document = fdm.getCachedDocument(file);
+        final Document document = FileDocumentManager.getInstance().getCachedDocument(file);
         if (document != null) {
           final int offset = calculateOffset(myProject, file, document, line, column);
           return document.createRangeMarker(offset, offset, persistent);
@@ -122,7 +123,7 @@
     }
 
     @Nullable
-    private RangeMarker getOrCreateDelegate() {
+    protected final RangeMarker getOrCreateDelegate() {
       if (myDelegate == null) {
         Document document = FileDocumentManager.getInstance().getDocument(myFile);
         if (document == null) {
@@ -218,6 +219,18 @@
 
       return document.createRangeMarker(offset, offset);
     }
+
+    @Override
+    public int getStartOffset() {
+      getOrCreateDelegate();
+      return super.getStartOffset();
+    }
+
+    @Override
+    public int getEndOffset() {
+      getOrCreateDelegate();
+      return super.getEndOffset();
+    }
   }
 
   private static int calculateOffset(@NotNull Project project, @NotNull VirtualFile file, @NotNull Document document, final int line, final int column) {
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java
index 28bc0f0..1e49937 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java
@@ -64,18 +64,7 @@
       try {
         final String str = String.valueOf(charTyped);
         CommandProcessor.getInstance().setCurrentCommandName(EditorBundle.message("typing.in.editor.command.name"));
-
-        if (editor.getCaretModel().getAllCarets().size() == 1) { // temporary fix for completion - going forward we shouldn't use this check
-          EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, str, true);
-        }
-        else {
-          editor.getCaretModel().runForEachCaret(new CaretAction() {
-            @Override
-            public void perform(Caret caret) {
-              EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, str, true);
-            }
-          });
-        }
+        EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, str, true);
       }
       catch (ReadOnlyFragmentModificationException e) {
         EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e);
diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java
index 9561581..c9e3a0f 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java
@@ -55,31 +55,38 @@
   private boolean myUseCurrentWindow = false;
 
   public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, int offset) {
-    this(project, file, -1, -1, offset, false);
+    this(project, file, -1, -1, offset, null, false);
   }
 
   public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, int logicalLine, int logicalColumn) {
-    this(project, file, logicalLine, logicalColumn, -1, false);
+    this(project, file, logicalLine, logicalColumn, -1, null, false);
   }
 
   public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file,
                             int logicalLine, int logicalColumn, boolean persistent) {
-    this(project, file, logicalLine, logicalColumn, -1, persistent);
+    this(project, file, logicalLine, logicalColumn, -1, null, persistent);
   }
 
   public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file) {
-    this(project, file, -1, -1, -1, false);
+    this(project, file, -1, -1, -1, null, false);
+  }
+
+  public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, @NotNull RangeMarker rangeMarker) {
+    this(project, file, -1, -1, -1, rangeMarker, false);
   }
 
   private OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file,
-                             int logicalLine, int logicalColumn, int offset, boolean persistent) {
+                             int logicalLine, int logicalColumn, int offset, @Nullable RangeMarker rangeMarker, boolean persistent) {
     myProject = project;
 
     myFile = file;
     myLogicalLine = logicalLine;
     myLogicalColumn = logicalColumn;
     myOffset = offset;
-    if (offset >= 0) {
+    if (rangeMarker != null) {
+      myRangeMarker = rangeMarker;
+    }
+    else if (offset >= 0) {
       myRangeMarker = LazyRangeMarkerFactory.getInstance(project).createRangeMarker(file, offset);
     }
     else if (logicalLine >= 0 ){
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java
index b4502de..3078888 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java
@@ -219,7 +219,7 @@
   /**
    * @return number of button pressed: from 0 up to options.length-1 inclusive, or -1 for Cancel
    */
-  public static int showDialog(Component parent, String message, @NotNull String title, @NotNull String[] options, int defaultOptionIndex, @Nullable Icon icon) {
+  public static int showDialog(@NotNull Component parent, String message, @NotNull String title, @NotNull String[] options, int defaultOptionIndex, @Nullable Icon icon) {
     if (isApplicationInUnitTestOrHeadless()) {
       return ourTestImplementation.show(message);
     }
@@ -309,7 +309,7 @@
     showDialog(project, message, title, new String[]{OK_BUTTON}, 0, icon);
   }
 
-  public static void showMessageDialog(Component parent, String message, @NotNull String title, @Nullable Icon icon) {
+  public static void showMessageDialog(@NotNull Component parent, String message, @NotNull String title, @Nullable Icon icon) {
     try {
       if (canShowMacSheetPanel()) {
         MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(parent));
@@ -386,7 +386,7 @@
    * @return {@link #YES} if user pressed "Yes" or {@link #NO} if user pressed "No" button.
    */
   @YesNoResult
-  public static int showYesNoDialog(Component parent, String message, @NotNull String title, @Nullable Icon icon) {
+  public static int showYesNoDialog(@NotNull Component parent, String message, @NotNull String title, @Nullable Icon icon) {
     try {
       if (canShowMacSheetPanel()) {
         return MacMessages.getInstance().showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON, SwingUtilities.getWindowAncestor(parent));
@@ -508,7 +508,7 @@
    * @return {@link #OK} if user pressed "Ok" or {@link #CANCEL} if user pressed "Cancel" button.
    */
   @OkCancelResult
-  public static int showOkCancelDialog(Component parent, String message, @NotNull String title, @NotNull String okText, @NotNull String cancelText, Icon icon) {
+  public static int showOkCancelDialog(@NotNull Component parent, String message, @NotNull String title, @NotNull String okText, @NotNull String cancelText, Icon icon) {
     try {
       if (canShowMacSheetPanel()) {
         int result =
@@ -526,7 +526,7 @@
    * @return {@link #OK} if user pressed "Ok" or {@link #CANCEL} if user pressed "Cancel" button.
    */
   @OkCancelResult
-  public static int showOkCancelDialog(Component parent, String message, String title, Icon icon) {
+  public static int showOkCancelDialog(@NotNull Component parent, String message, String title, Icon icon) {
     return showOkCancelDialog(parent, message, title, OK_BUTTON, CANCEL_BUTTON, icon);
   }
 
@@ -619,7 +619,7 @@
     showDialog(project, message, title, new String[]{OK_BUTTON}, 0, getErrorIcon());
   }
 
-  public static void showErrorDialog(Component component, String message, @Nls @NotNull String title) {
+  public static void showErrorDialog(@NotNull Component component, String message, @Nls @NotNull String title) {
     try {
       if (canShowMacSheetPanel()) {
         MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(component));
@@ -632,7 +632,7 @@
     showDialog(component, message, title, new String[]{OK_BUTTON}, 0, getErrorIcon());
   }
 
-  public static void showErrorDialog(Component component, String message) {
+  public static void showErrorDialog(@NotNull Component component, String message) {
     try {
       if (canShowMacSheetPanel()) {
         MacMessages.getInstance().showErrorDialog(CommonBundle.getErrorTitle(), message, OK_BUTTON, SwingUtilities.getWindowAncestor(
@@ -678,7 +678,7 @@
     showDialog(project, message, title, new String[]{OK_BUTTON}, 0, getWarningIcon());
   }
 
-  public static void showWarningDialog(Component component, String message, @NotNull String title) {
+  public static void showWarningDialog(@NotNull Component component, String message, @NotNull String title) {
     try {
       if (canShowMacSheetPanel()) {
         MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(component));
@@ -751,7 +751,7 @@
    * @return {@link #YES} if user pressed "Yes" or {@link #NO} if user pressed "No", or {@link #CANCEL} if user pressed "Cancel" button.
    */
   @YesNoCancelResult
-  public static int showYesNoCancelDialog(Component parent,
+  public static int showYesNoCancelDialog(@NotNull Component parent,
                                           String message,
                                           @NotNull String title,
                                           @NotNull String yes,
@@ -775,7 +775,7 @@
    * @return {@link #YES} if user pressed "Yes" or {@link #NO} if user pressed "No", or {@link #CANCEL} if user pressed "Cancel" button.
    */
   @YesNoCancelResult
-  public static int showYesNoCancelDialog(Component parent, String message, String title, Icon icon) {
+  public static int showYesNoCancelDialog(@NotNull Component parent, String message, String title, Icon icon) {
     return showYesNoCancelDialog(parent, message, title, YES_BUTTON, NO_BUTTON, CANCEL_BUTTON, icon);
   }
 
@@ -878,7 +878,7 @@
    * @return trimmed input string or <code>null</code> if user cancelled dialog.
    */
   @Nullable
-  public static String showInputDialog(Component parent, String message, String title, @Nullable Icon icon) {
+  public static String showInputDialog(@NotNull Component parent, String message, String title, @Nullable Icon icon) {
     return showInputDialog(parent, message, title, icon, null, null);
   }
 
@@ -942,7 +942,7 @@
   }
 
   @Nullable
-  public static String showInputDialog(Component parent,
+  public static String showInputDialog(@NotNull Component parent,
                                        String message,
                                        String title,
                                        @Nullable Icon icon,
@@ -1051,7 +1051,7 @@
 
   /** @deprecated It looks awful! */
   @Deprecated
-  public static int showChooseDialog(Component parent, String message, String title, String[] values, String initialValue, Icon icon) {
+  public static int showChooseDialog(@NotNull Component parent, String message, String title, String[] values, String initialValue, Icon icon) {
     if (isApplicationInUnitTestOrHeadless()) {
       return ourTestImplementation.show(message);
     }
@@ -1250,15 +1250,15 @@
       _init(title, message, options, defaultOptionIndex, focusedOptionIndex, icon, null);
     }
 
-    public MessageDialog(Component parent, String message, String title, @NotNull String[] options, int defaultOptionIndex, @Nullable Icon icon) {
+    public MessageDialog(@NotNull Component parent, String message, String title, @NotNull String[] options, int defaultOptionIndex, @Nullable Icon icon) {
       this(parent, message, title, options, defaultOptionIndex, icon, false);
     }
 
-    public MessageDialog(Component parent, String message, String title, @NotNull String[] options, int defaultOptionIndex, @Nullable Icon icon, boolean canBeParent) {
+    public MessageDialog(@NotNull Component parent, String message, String title, @NotNull String[] options, int defaultOptionIndex, @Nullable Icon icon, boolean canBeParent) {
       this(parent, message, title, options, defaultOptionIndex, -1, icon, canBeParent);
     }
 
-    public MessageDialog(Component parent,
+    public MessageDialog(@NotNull Component parent,
                          String message,
                          String title,
                          @NotNull String[] options,
@@ -1644,7 +1644,7 @@
       this(project, message, title, icon, initialValue, validator, new String[]{OK_BUTTON, CANCEL_BUTTON}, 0);
     }
 
-    public InputDialog(Component parent,
+    public InputDialog(@NotNull Component parent,
                        String message,
                        String title,
                        @Nullable Icon icon,
@@ -1881,7 +1881,7 @@
       this(project, message, title, icon, values, initialValue, new String[]{OK_BUTTON, CANCEL_BUTTON}, 0);
     }
 
-    public ChooseDialog(Component parent, String message, String title, @Nullable Icon icon, String[] values, String initialValue) {
+    public ChooseDialog(@NotNull Component parent, String message, String title, @Nullable Icon icon, String[] values, String initialValue) {
       super(parent, message, title, new String[]{OK_BUTTON, CANCEL_BUTTON}, 0, icon);
       myComboBox.setModel(new DefaultComboBoxModel(values));
       myComboBox.setSelectedItem(initialValue);
diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/impl/StubVirtualFile.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/impl/StubVirtualFile.java
index 4876545..7d39175 100644
--- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/impl/StubVirtualFile.java
+++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/impl/StubVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -30,69 +30,85 @@
 import java.io.OutputStream;
 
 public class StubVirtualFile extends VirtualFile {
+  @Override
   @NotNull
   public byte[] contentsToByteArray() throws IOException {
     throw new UnsupportedOperationException("contentsToByteArray is not implemented");
   }
 
+  @Override
   public VirtualFile[] getChildren() {
     throw new UnsupportedOperationException("getChildren is not implemented");
   }
 
+  @Override
   @NotNull
   public VirtualFileSystem getFileSystem() {
     throw new UnsupportedOperationException("getFileSystem is not implemented");
   }
 
+  @Override
   public InputStream getInputStream() throws IOException {
     throw new UnsupportedOperationException("getInputStream is not implemented");
   }
 
+  @Override
   public long getLength() {
     throw new UnsupportedOperationException("getLength is not implemented");
   }
 
+  @Override
   @NotNull
   @NonNls
   public String getName() {
     throw new UnsupportedOperationException("getName is not implemented");
   }
 
+  @Override
   @NotNull
   public OutputStream getOutputStream(final Object requestor, final long newModificationStamp, final long newTimeStamp) throws IOException {
     throw new UnsupportedOperationException("getOutputStream is not implemented");
   }
 
+  @Override
   @Nullable
   public VirtualFile getParent() {
     throw new UnsupportedOperationException("getParent is not implemented");
   }
 
+  @Override
+  @NotNull
   public String getPath() {
     throw new UnsupportedOperationException("getPath is not implemented");
   }
 
+  @Override
   public long getTimeStamp() {
     throw new UnsupportedOperationException("getTimeStamp is not implemented");
   }
 
+  @Override
   @NotNull
   public String getUrl() {
     throw new UnsupportedOperationException("getUrl is not implemented");
   }
 
+  @Override
   public boolean isDirectory() {
     throw new UnsupportedOperationException("isDirectory is not implemented");
   }
 
+  @Override
   public boolean isValid() {
     throw new UnsupportedOperationException("isValid is not implemented");
   }
 
+  @Override
   public boolean isWritable() {
     throw new UnsupportedOperationException("isWritable is not implemented");
   }
 
+  @Override
   public void refresh(final boolean asynchronous, final boolean recursive, final Runnable postRunnable) {
     throw new UnsupportedOperationException("refresh is not implemented");
   }
diff --git a/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java b/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java
index 0c76911..6737528 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/IdeGlassPaneUtil.java
@@ -16,11 +16,12 @@
 
 package com.intellij.openapi.wm;
 
-import com.intellij.openapi.ui.Painter;
 import com.intellij.openapi.Disposable;
+import com.intellij.openapi.ui.Painter;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
 import com.intellij.openapi.util.Disposer;
-import com.intellij.util.ui.update.UiNotifyConnector;
 import com.intellij.util.ui.update.Activatable;
+import com.intellij.util.ui.update.UiNotifyConnector;
 
 import javax.swing.*;
 import java.awt.*;
@@ -69,6 +70,9 @@
 
   public static boolean canBePreprocessed(MouseEvent e) {
     Component c = SwingUtilities.getDeepestComponentAt(e.getComponent(), e.getX(), e.getY());
+    if (JBPopupFactory.getInstance().getParentBalloonFor(c) != null) {
+      return false;
+    }
 
     if (c instanceof IdeGlassPane.TopComponent) {
       return ((IdeGlassPane.TopComponent)c).canBePreprocessed(e);
diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java
index 1faa21b..d8736f6 100644
--- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java
+++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java
@@ -340,6 +340,9 @@
 
   @Override
   public void paint(Graphics g) {
+    if (!isEnabled()) {
+      g = new TableGrayer((Graphics2D)g);
+    }
     super.paint(g);
     if (myBusyIcon != null) {
       myBusyIcon.updateLocation(this);
@@ -661,6 +664,13 @@
   protected class JBTableHeader extends JTableHeader {
     public JBTableHeader() {
       super(JBTable.this.columnModel);
+      JBTable.this.addPropertyChangeListener(new PropertyChangeListener() {
+        @Override
+        public void propertyChange(PropertyChangeEvent evt) {
+          JBTableHeader.this.revalidate();
+          JBTableHeader.this.repaint();
+        }
+      });
     }
 
     @Override
@@ -668,6 +678,9 @@
       if (myEnableAntialiasing) {
         GraphicsUtil.setupAntialiasing(g);
       }
+      if (!JBTable.this.isEnabled()) {
+        g = new TableGrayer((Graphics2D)g);
+      }
       super.paint(g);
     }
 
@@ -686,5 +699,30 @@
       return super.getToolTipText(event);
     }
   }
+
+  /**
+   * Make it possible to disable a JBTable
+   *
+   * @author Konstantin Bulenkov
+   */
+  private final class TableGrayer extends Graphics2DDelegate {
+    public TableGrayer(Graphics2D g2d) {
+      super(g2d);
+    }
+
+    @Override
+    public void setColor(Color color) {
+      if (!UIUtil.isUnderDarcula() || !JBTable.this.getBackground().equals(color)) {
+        //noinspection UseJBColor
+        color = new Color(UIUtil.getGrayFilter().filterRGB(0, 0, color.getRGB()));
+      }
+      super.setColor(color);
+    }
+
+    @Override
+    public Graphics create() {
+      return new TableGrayer((Graphics2D)super.create());
+    }
+  }
 }
 
diff --git a/platform/platform-api/src/com/intellij/util/Alarm.java b/platform/platform-api/src/com/intellij/util/Alarm.java
index 269b81b..60d3233 100644
--- a/platform/platform-api/src/com/intellij/util/Alarm.java
+++ b/platform/platform-api/src/com/intellij/util/Alarm.java
@@ -69,6 +69,10 @@
     }
   }
 
+  public void checkDisposed() {
+    LOG.assertTrue(!myDisposed, "Already disposed");
+  }
+
   public enum ThreadToUse {
     SWING_THREAD,
     SHARED_THREAD,
@@ -158,7 +162,7 @@
 
   protected void _addRequest(@NotNull Runnable request, long delayMillis, ModalityState modalityState) {
     synchronized (LOCK) {
-      LOG.assertTrue(!myDisposed, "Already disposed");
+      checkDisposed();
       final Request requestToSchedule = new Request(request, modalityState, delayMillis);
 
       if (myActivationComponent == null || myActivationComponent.isShowing()) {
diff --git a/platform/platform-api/src/com/intellij/util/ui/Animator.java b/platform/platform-api/src/com/intellij/util/ui/Animator.java
index a7d9301..9b02560 100644
--- a/platform/platform-api/src/com/intellij/util/ui/Animator.java
+++ b/platform/platform-api/src/com/intellij/util/ui/Animator.java
@@ -131,7 +131,10 @@
 
   public void resume() {
     final Application app = ApplicationManager.getApplication();
-    if (app == null || app.isUnitTestMode()) return;
+    if (app == null || app.isUnitTestMode()) {
+      animationDone();
+      return;
+    }
 
     if (myCycleDuration == 0) {
       myCurrentFrame = myTotalFrames - 1;
diff --git a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java
index 97ecd97..d9a1ba7 100644
--- a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java
+++ b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java
@@ -787,9 +787,9 @@
       if (rowCount == oldRowCount) break;
       oldRowCount = rowCount;
       for (int i = 0; i < rowCount; i++) {
-        tree.expandRow(i);
+          tree.expandRow(i);
+        }
      }
-    }
     while (true);
   }
 
diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java
index caecb4c..c4c8c8f 100644
--- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java
@@ -104,7 +104,7 @@
     myAnActionListener = new MyAnActionListener();
     actionManagerEx.addAnActionListener(myAnActionListener);
 
-    myCaretMoveListener = new CaretListener() {
+    myCaretMoveListener = new CaretAdapter() {
       @Override
       public void caretPositionChanged(CaretEvent e) {
         hideHints(HIDE_BY_ANY_KEY, false, false);
@@ -131,6 +131,7 @@
     myEditorFocusListener = new FocusAdapter() {
       @Override
       public void focusLost(final FocusEvent e) {
+        if (UIUtil.isFocusProxy(e.getOppositeComponent())) return;
         myHideAlarm.addRequest(new Runnable() {
           @Override
           public void run() {
diff --git a/platform/platform-impl/src/com/intellij/designer/model/Property.java b/platform/platform-impl/src/com/intellij/designer/model/Property.java
index b44b599..9f902c8 100644
--- a/platform/platform-impl/src/com/intellij/designer/model/Property.java
+++ b/platform/platform-impl/src/com/intellij/designer/model/Property.java
@@ -120,6 +120,10 @@
     return false;
   }
 
+  public boolean closeEditorDuringRefresh() {
+    return false;
+  }
+
   //////////////////////////////////////////////////////////////////////////////////////////
   //
   // Presentation
diff --git a/platform/platform-impl/src/com/intellij/designer/propertyTable/PropertyTable.java b/platform/platform-impl/src/com/intellij/designer/propertyTable/PropertyTable.java
index 9ea8047..e8deef9 100644
--- a/platform/platform-impl/src/com/intellij/designer/propertyTable/PropertyTable.java
+++ b/platform/platform-impl/src/com/intellij/designer/propertyTable/PropertyTable.java
@@ -848,7 +848,7 @@
 
     if (isSetValue) {
       if (property.needRefreshPropertyList() || needRefresh[0]) {
-        update(myContainers, null, false);
+        update(myContainers, null, property.closeEditorDuringRefresh());
       }
       else {
         myModel.fireTableRowsUpdated(row, row);
@@ -1113,7 +1113,7 @@
         }
 
         if (setValueAtRow(editingRow, value)) {
-          if (!continueEditing) {
+          if (!continueEditing && editingRow != -1) {
             PropertyEditor editor = myProperties.get(editingRow).getEditor();
             editor.removePropertyEditorListener(myPropertyEditorListener);
             removeEditor();
diff --git a/platform/platform-impl/src/com/intellij/execution/process/ScriptRunnerUtil.java b/platform/platform-impl/src/com/intellij/execution/process/ScriptRunnerUtil.java
index cf95958..9933dd5 100644
--- a/platform/platform-impl/src/com/intellij/execution/process/ScriptRunnerUtil.java
+++ b/platform/platform-impl/src/com/intellij/execution/process/ScriptRunnerUtil.java
@@ -227,6 +227,9 @@
                                              long millisTimeout,
                                              @Nullable String commandLine) {
     if (processHandler.isProcessTerminated()) {
+      if (commandLine == null && processHandler instanceof BaseOSProcessHandler) {
+        commandLine = ((BaseOSProcessHandler) processHandler).getCommandLine();
+      }
       LOG.warn("Process '" + commandLine + "' is already terminated!");
       return;
     }
diff --git a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
index 6e6c052..39886a2 100644
--- a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
+++ b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.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.
@@ -33,6 +33,7 @@
 import com.intellij.openapi.wm.WindowManager;
 import com.intellij.ui.HyperlinkAdapter;
 import com.intellij.ui.awt.RelativePoint;
+import com.intellij.util.SystemProperties;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.PropertyKey;
 
@@ -119,6 +120,10 @@
   }
 
   private static void startDiskSpaceMonitoring() {
+    if (SystemProperties.getBooleanProperty("idea.no.system.path.space.monitoring", false)) {
+      return;
+    }
+
     final File file = new File(PathManager.getSystemPath());
     final AtomicBoolean reported = new AtomicBoolean();
     final ThreadLocal<Future<Long>> ourFreeSpaceCalculation = new ThreadLocal<Future<Long>>();
diff --git a/platform/platform-impl/src/com/intellij/ide/dnd/FileCopyPasteUtil.java b/platform/platform-impl/src/com/intellij/ide/dnd/FileCopyPasteUtil.java
index cecde70..dca050b 100644
--- a/platform/platform-impl/src/com/intellij/ide/dnd/FileCopyPasteUtil.java
+++ b/platform/platform-impl/src/com/intellij/ide/dnd/FileCopyPasteUtil.java
@@ -51,8 +51,8 @@
 
   public static DataFlavor createDataFlavor(@NotNull final String mimeType, @Nullable final Class<?> klass, final boolean register) {
     try {
-      final String typeString = klass != null ? mimeType + ";class=" + klass.getName() : mimeType;
-      final DataFlavor flavor = new DataFlavor(typeString);
+      final DataFlavor flavor =
+        klass != null ? new DataFlavor(mimeType + ";class=" + klass.getName(), null, klass.getClassLoader()) : new DataFlavor(mimeType);
 
       if (register) {
         final FlavorMap map = SystemFlavorMap.getDefaultFlavorMap();
diff --git a/platform/platform-impl/src/com/intellij/ide/impl/SelectInEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/impl/SelectInEditorManagerImpl.java
index 6c7efde..2eebf98 100644
--- a/platform/platform-impl/src/com/intellij/ide/impl/SelectInEditorManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/impl/SelectInEditorManagerImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -143,6 +143,14 @@
     releaseAll();
   }
 
+  @Override
+  public void caretAdded(CaretEvent e) {
+  }
+
+  @Override
+  public void caretRemoved(CaretEvent e) {
+  }
+
   private void releaseAll() {
     if (mySegmentHighlighter != null && myEditor != null){
       mySegmentHighlighter.dispose();
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java
index e6664c0..285efb4 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java
@@ -83,6 +83,7 @@
     //data
     myName.setText("<html><body>" + plugin.getName() + "</body></html>");
     myCategory.setText(plugin.getCategory() == null ? "UNKNOWN" : plugin.getCategory().toUpperCase());
+    final boolean hasNewerVersion = InstalledPluginsTableModel.hasNewerVersion(plugin.getPluginId());
     if (plugin instanceof PluginNode) {
       final PluginNode node = (PluginNode)plugin;
 
@@ -93,7 +94,7 @@
       myUpdated.setText("Updated " + DateFormatUtil.formatDate(node.getDate()));
       switch (node.getStatus()) {
         case PluginNode.STATUS_INSTALLED:
-          myActionId = InstalledPluginsTableModel.hasNewerVersion(plugin.getPluginId()) ? ACTION_ID.UPDATE : ACTION_ID.UNINSTALL;
+          myActionId = hasNewerVersion ? ACTION_ID.UPDATE : ACTION_ID.UNINSTALL;
           break;
         case PluginNode.STATUS_DOWNLOADED:
           myActionId = ACTION_ID.RESTART;
@@ -114,10 +115,10 @@
       final String version = plugin.getVersion();
       myVersion.setText("Version: " + (version == null ? "N/A" : version));
       myUpdated.setVisible(false);
-      if (!plugin.isBundled()) {
+      if (!plugin.isBundled() || hasNewerVersion) {
         if (((IdeaPluginDescriptorImpl)plugin).isDeleted()) {
           myActionId = ACTION_ID.RESTART;
-        } else if (InstalledPluginsTableModel.hasNewerVersion(plugin.getPluginId())) {
+        } else if (hasNewerVersion) {
           myActionId = ACTION_ID.UPDATE;
         } else {
           myActionId = ACTION_ID.UNINSTALL;
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java
index 174ca5a..3b2ac05 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java
@@ -17,6 +17,7 @@
 
 import com.intellij.icons.AllIcons;
 import com.intellij.openapi.extensions.PluginId;
+import com.intellij.openapi.util.IconLoader;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.vcs.FileStatus;
 import com.intellij.ui.Gray;
@@ -93,6 +94,11 @@
       }
       if (myPluginDescriptor.isBundled()) {
         myCategory.setText(myCategory.getText() + "[Bundled]");
+        myStatus.setIcon(AllIcons.Nodes.PluginJB);
+      }
+      final String vendor = myPluginDescriptor.getVendor();
+      if (vendor != null && vendor.toLowerCase().contains("jetbrains")) {
+        myStatus.setIcon(AllIcons.Nodes.PluginJB);
       }
 
       myPanel.setBackground(bg);
@@ -120,6 +126,7 @@
         if (!isSelected) myName.setForeground(FileStatus.ADDED.getColor());
         //todo[kb] set proper icon
         //myStatus.setText("[Downloaded]");
+        myStatus.setIcon(AllIcons.Nodes.PluginRestart);
         //myPanel.setToolTipText(IdeBundle.message("plugin.download.status.tooltip"));
         //myStatus.setBorder(BorderFactory.createEmptyBorder(0, LEFT_MARGIN, 0, 0));
       }
@@ -136,6 +143,16 @@
         //todo[kb] set proper icon
         //myStatus.setText("v." + pluginNode.getInstalledVersion() + (hasNewerVersion ? (" -> " + pluginNode.getVersion()) : ""));
       }
+
+      if (InstalledPluginsTableModel.hasNewerVersion(myPluginDescriptor.getPluginId())) {
+        myStatus.setIcon(AllIcons.Nodes.Pluginobsolete);
+        if (!isSelected) {
+          myName.setForeground(JBColor.RED);
+        }
+      }
+      if (!myPluginDescriptor.isEnabled()) {
+        myStatus.setIcon(IconLoader.getDisabledIcon(myStatus.getIcon()));
+      }
     }
 
     return myPanel;
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
index f858002..818466b 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
@@ -273,6 +273,10 @@
   }
 
   protected Object parseValue(String key, @NotNull String value) {
+    if ("null".equals(value)) {
+      return null;
+    }
+
     if (key.endsWith("Insets")) {
       final List<String> numbers = StringUtil.split(value, ",");
       return new InsetsUIResource(Integer.parseInt(numbers.get(0)),
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
index b975ff8..1f29a08 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
@@ -122,6 +122,9 @@
 Button.darcula.selectedButtonForeground=bbbbbb
 Button.darcula.disabledText.shadow=00000000
 
+ToggleButton.border=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonPainter
+ToggleButtonUI=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI
+
 MenuItem.acceleratorForeground=eeeeee
 PopupMenu.translucentBackground=3c3f41
 
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonUI.java
index f4fbc75..8deb957 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonUI.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonUI.java
@@ -50,7 +50,7 @@
       final Insets ins = border.getBorderInsets(c);
       final int yOff = (ins.top + ins.bottom) / 4;
       if (!square) {
-        if (((JButton)c).isDefaultButton()) {
+        if (c instanceof JButton && ((JButton)c).isDefaultButton()) {
           ((Graphics2D)g).setPaint(UIUtil.getGradientPaint(0, 0, getSelectedButtonColor1(), 0, c.getHeight(), getSelectedButtonColor2()));
         }
         else {
@@ -100,7 +100,7 @@
   @Override
   public void update(Graphics g, JComponent c) {
     super.update(g, c);
-    if (((JButton)c).isDefaultButton() && !SystemInfo.isMac) {
+    if (c instanceof JButton && ((JButton)c).isDefaultButton() && !SystemInfo.isMac) {
       if (!c.getFont().isBold()) {
        c.setFont(c.getFont().deriveFont(Font.BOLD));
       }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaToggleButtonUI.java
similarity index 61%
copy from platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
copy to platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaToggleButtonUI.java
index 72c585b..b35ac61 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaToggleButtonUI.java
@@ -13,18 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk2;
+package com.intellij.ide.ui.laf.darcula.ui;
 
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.util.Consumer;
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
 
-/**
- * @author traff
- */
-public interface RemoteSdkProducer<T extends RemoteSdkCredentials> {
-  T getRemoteSdkCredentials() throws InterruptedException;
-  
-  void produceRemoteSdkCredentials(Consumer<T> remoteSdkConsumer);
-
-  Object getRemoteSdkDataKey();
+public class DarculaToggleButtonUI extends DarculaButtonUI {
+  @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass")
+  public static ComponentUI createUI(JComponent c) {
+    return new DarculaToggleButtonUI();
+  }
 }
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties
index 116adfe..cd99cb1 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties
@@ -130,6 +130,9 @@
 Button.darcula.selectedButtonForeground=f0f0f0
 Button.darcula.disabledText.shadow=ffffff
 
+ToggleButton.border=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonPainter
+ToggleButtonUI=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI
+
 MenuItem.acceleratorForeground=505050
 PopupMenu.translucentBackground=e8e8e8
 
diff --git a/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java b/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java
index 14e6d92..855c898 100644
--- a/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java
+++ b/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.TimeoutUtil;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.Arrays;
 
@@ -50,14 +51,15 @@
           return 0;
         }
 
-        public VirtualFile[] queryNeededFiles(ProgressIndicator indicator) {
+        @NotNull
+        public VirtualFile[] queryNeededFiles(@NotNull ProgressIndicator indicator) {
           while (myDumb) {
             TimeoutUtil.sleep(100);
           }
           return VirtualFile.EMPTY_ARRAY;
         }
 
-        public void processFile(FileContent fileContent) {
+        public void processFile(@NotNull FileContent fileContent) {
         }
 
         public void updatingDone() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/DiffPanelComboBoxAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/DiffPanelComboBoxAction.java
new file mode 100644
index 0000000..b3ef959
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/DiffPanelComboBoxAction.java
@@ -0,0 +1,94 @@
+package com.intellij.openapi.diff.actions;
+
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
+import com.intellij.openapi.diff.DiffBundle;
+import com.intellij.openapi.diff.ex.DiffPanelEx;
+import com.intellij.openapi.diff.impl.DiffPanelImpl;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.Map;
+
+public abstract class DiffPanelComboBoxAction<T> extends ComboBoxAction implements DumbAware {
+  @NotNull private final Map<T, AnAction> myActions = new HashMap<T, AnAction>();
+  @NotNull private final T[] myActionOrder;
+
+  protected DiffPanelComboBoxAction(@NotNull T[] actionOrder) {
+    myActionOrder = actionOrder;
+  }
+
+  @NotNull
+  protected abstract String getActionName();
+
+  @NotNull
+  protected abstract T getCurrentOption(@NotNull DiffPanelEx diffPanel);
+
+  @Nullable
+  private static DiffPanelEx getDiffPanel(@NotNull DataContext context) {
+    return DiffPanelImpl.fromDataContext(context);
+  }
+
+  protected void addAction(T key, @NotNull AnAction action) {
+    myActions.put(key, action);
+  }
+
+  @Override
+  public JComponent createCustomComponent(final Presentation presentation) {
+    JPanel panel = new JPanel(new BorderLayout());
+    final JLabel label = new JLabel(getActionName());
+    label.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
+    panel.add(label, BorderLayout.WEST);
+    panel.add(super.createCustomComponent(presentation), BorderLayout.CENTER);
+    return panel;
+  }
+
+  @NotNull
+  @Override
+  protected DefaultActionGroup createPopupActionGroup(JComponent button) {
+    DefaultActionGroup actionGroup = new DefaultActionGroup();
+    for (T option : myActionOrder) {
+      actionGroup.add(myActions.get(option));
+    }
+    return actionGroup;
+  }
+
+  @Override
+  public void update(AnActionEvent e) {
+    super.update(e);
+    Presentation presentation = e.getPresentation();
+    DiffPanelEx diffPanel = getDiffPanel(e.getDataContext());
+    if (diffPanel != null && diffPanel.getComponent().isDisplayable()) {
+      AnAction action = myActions.get(getCurrentOption(diffPanel));
+      Presentation templatePresentation = action.getTemplatePresentation();
+      presentation.setIcon(templatePresentation.getIcon());
+      presentation.setText(templatePresentation.getText());
+      presentation.setEnabled(true);
+    }
+    else {
+      presentation.setIcon(null);
+      presentation.setText(DiffBundle.message("diff.panel.combo.box.action.not.available.action.name"));
+      presentation.setEnabled(false);
+    }
+  }
+
+  protected static abstract class DiffPanelAction extends DumbAwareAction {
+    public DiffPanelAction(@NotNull String text) {
+      super(text);
+    }
+
+    public void actionPerformed(AnActionEvent e) {
+      final DiffPanelEx diffPanel = getDiffPanel(e.getDataContext());
+      if (diffPanel != null) {
+        perform(diffPanel);
+      }
+    }
+
+    protected abstract void perform(@NotNull DiffPanelEx diffPanel);
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java
index 8ae6fa2..65f5eb3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java
@@ -15,89 +15,48 @@
  */
 package com.intellij.openapi.diff.actions;
 
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.DefaultActionGroup;
-import com.intellij.openapi.actionSystem.Presentation;
-import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
 import com.intellij.openapi.diff.DiffBundle;
 import com.intellij.openapi.diff.ex.DiffPanelEx;
-import com.intellij.openapi.diff.impl.DiffPanelImpl;
 import com.intellij.openapi.diff.impl.processing.HighlightMode;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.DumbAwareAction;
-import com.intellij.util.containers.HashMap;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.*;
-import java.awt.*;
-import java.util.Map;
-
-public class HighlightModeAction extends ComboBoxAction implements DumbAware {
-  private final Map<HighlightMode, AnAction> myActions = new HashMap<HighlightMode, AnAction>();
-  private static final HighlightMode[] ourActionOrder =
-    new HighlightMode[]{HighlightMode.BY_WORD, HighlightMode.BY_LINE, HighlightMode.NO_HIGHLIGHTING};
+public class HighlightModeAction extends DiffPanelComboBoxAction<HighlightMode> {
+  private static final HighlightMode[] ourActionOrder = new HighlightMode[]{
+    HighlightMode.BY_WORD,
+    HighlightMode.BY_LINE,
+    HighlightMode.NO_HIGHLIGHTING
+  };
 
   public HighlightModeAction() {
-    myActions.put(HighlightMode.BY_WORD,
-                  new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.word"), HighlightMode.BY_WORD));
-    myActions.put(HighlightMode.BY_LINE,
-                  new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.line"), HighlightMode.BY_LINE));
-    myActions.put(HighlightMode.NO_HIGHLIGHTING,
-                  new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.no.highlighting"),
-                                             HighlightMode.NO_HIGHLIGHTING));
-  }
-
-  @Override
-  public JComponent createCustomComponent(final Presentation presentation) {
-    JPanel panel = new JPanel(new BorderLayout());
-    final JLabel label = new JLabel(DiffBundle.message("diff.acton.highlight.mode.action.name"));
-    label.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
-    panel.add(label, BorderLayout.WEST);
-    panel.add(super.createCustomComponent(presentation), BorderLayout.CENTER);
-    return panel;
+    super(ourActionOrder);
+    addAction(HighlightMode.BY_WORD, new HighlightingModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.word"), HighlightMode.BY_WORD));
+    addAction(HighlightMode.BY_LINE, new HighlightingModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.line"), HighlightMode.BY_LINE));
+    addAction(HighlightMode.NO_HIGHLIGHTING, new HighlightingModeAction(DiffBundle.message("diff.acton.highlight.mode.action.no.highlighting"), HighlightMode.NO_HIGHLIGHTING));
   }
 
   @NotNull
-  protected DefaultActionGroup createPopupActionGroup(JComponent button) {
-    DefaultActionGroup actionGroup = new DefaultActionGroup();
-    for (HighlightMode comparisonPolicy : ourActionOrder) {
-      actionGroup.add(myActions.get(comparisonPolicy));
-    }
-    return actionGroup;
+  @Override
+  protected String getActionName() {
+    return DiffBundle.message("diff.acton.highlight.mode.action.name");
   }
 
-  public void update(AnActionEvent e) {
-    super.update(e);
-    Presentation presentation = e.getPresentation();
-    DiffPanelEx diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
-    if (diffPanel != null && diffPanel.getComponent().isDisplayable()) {
-      AnAction action = myActions.get(diffPanel.getHighlightMode());
-      Presentation templatePresentation = action.getTemplatePresentation();
-      presentation.setIcon(templatePresentation.getIcon());
-      presentation.setText(templatePresentation.getText());
-      presentation.setEnabled(true);
-    }
-    else {
-      presentation.setIcon(null);
-      presentation.setText(DiffBundle.message("diff.acton.highlight.mode.not.available.action.name"));
-      presentation.setEnabled(false);
-    }
+  @NotNull
+  @Override
+  protected HighlightMode getCurrentOption(@NotNull DiffPanelEx diffPanel) {
+    return diffPanel.getHighlightMode();
   }
 
-  private static class SetHighlightModeAction extends DumbAwareAction {
+  private static class HighlightingModeAction extends DiffPanelAction {
     private final HighlightMode myHighlightMode;
 
-    public SetHighlightModeAction(String text, HighlightMode mode) {
+    public HighlightingModeAction(String text, HighlightMode highlightMode) {
       super(text);
-      myHighlightMode = mode;
+      myHighlightMode = highlightMode;
     }
 
-    public void actionPerformed(AnActionEvent e) {
-      final DiffPanelImpl diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
-      if (diffPanel != null) {
-        diffPanel.setHighlightMode(myHighlightMode);
-      }
+    @Override
+    protected void perform(@NotNull DiffPanelEx diffPanel) {
+      diffPanel.setHighlightMode(myHighlightMode);
     }
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/IgnoreWhiteSpacesAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/IgnoreWhiteSpacesAction.java
index 930db0e..a46d8b1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/IgnoreWhiteSpacesAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/IgnoreWhiteSpacesAction.java
@@ -15,74 +15,38 @@
  */
 package com.intellij.openapi.diff.actions;
 
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.DefaultActionGroup;
-import com.intellij.openapi.actionSystem.Presentation;
-import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
 import com.intellij.openapi.diff.DiffBundle;
 import com.intellij.openapi.diff.ex.DiffPanelEx;
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
-import com.intellij.openapi.diff.impl.DiffPanelImpl;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.DumbAwareAction;
-import com.intellij.util.containers.HashMap;
 import org.jetbrains.annotations.NotNull;
 
-import javax.swing.*;
-import java.awt.*;
-import java.util.Map;
-
-public class IgnoreWhiteSpacesAction extends ComboBoxAction implements DumbAware {
-  private final Map<ComparisonPolicy, AnAction> myActions = new HashMap<ComparisonPolicy, AnAction>();
+public class IgnoreWhiteSpacesAction extends DiffPanelComboBoxAction<ComparisonPolicy> {
   private static final ComparisonPolicy[] ourActionOrder = new ComparisonPolicy[]{
     ComparisonPolicy.DEFAULT,
     ComparisonPolicy.TRIM_SPACE,
-    ComparisonPolicy.IGNORE_SPACE};
+    ComparisonPolicy.IGNORE_SPACE
+  };
 
   public IgnoreWhiteSpacesAction() {
-    myActions.put(ComparisonPolicy.DEFAULT, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.do.not.ignore"), ComparisonPolicy.DEFAULT));
-    myActions.put(ComparisonPolicy.TRIM_SPACE, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.leading.and.trailing"), ComparisonPolicy.TRIM_SPACE));
-    myActions.put(ComparisonPolicy.IGNORE_SPACE, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.all"), ComparisonPolicy.IGNORE_SPACE));
-  }
-
-  @Override
-  public JComponent createCustomComponent(final Presentation presentation) {
-    JPanel panel = new JPanel(new BorderLayout());
-    final JLabel label = new JLabel(DiffBundle.message("ignore.whitespace.acton.name"));
-    label.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
-    panel.add(label, BorderLayout.WEST);
-    panel.add(super.createCustomComponent(presentation), BorderLayout.CENTER);
-    return panel;
+    super(ourActionOrder);
+    addAction(ComparisonPolicy.DEFAULT, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.do.not.ignore"), ComparisonPolicy.DEFAULT));
+    addAction(ComparisonPolicy.TRIM_SPACE, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.leading.and.trailing"), ComparisonPolicy.TRIM_SPACE));
+    addAction(ComparisonPolicy.IGNORE_SPACE, new IgnoringPolicyAction(DiffBundle.message("diff.acton.ignore.whitespace.policy.all"), ComparisonPolicy.IGNORE_SPACE));
   }
 
   @NotNull
-  protected DefaultActionGroup createPopupActionGroup(JComponent button) {
-    DefaultActionGroup actionGroup = new DefaultActionGroup();
-    for (ComparisonPolicy comparisonPolicy : ourActionOrder) {
-      actionGroup.add(myActions.get(comparisonPolicy));
-    }
-    return actionGroup;
+  @Override
+  protected String getActionName() {
+    return DiffBundle.message("ignore.whitespace.acton.name");
   }
 
-  public void update(AnActionEvent e) {
-    super.update(e);
-    Presentation presentation = e.getPresentation();
-    DiffPanelEx diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
-    if (diffPanel != null && diffPanel.getComponent().isDisplayable()) {
-      AnAction action = myActions.get(diffPanel.getComparisonPolicy());
-      Presentation templatePresentation = action.getTemplatePresentation();
-      presentation.setIcon(templatePresentation.getIcon());
-      presentation.setText(templatePresentation.getText());
-      presentation.setEnabled(true);
-    } else {
-      presentation.setIcon(null);
-      presentation.setText(DiffBundle.message("ignore.whitespace.action.not.available.action.name"));
-      presentation.setEnabled(false);
-    }
+  @NotNull
+  @Override
+  protected ComparisonPolicy getCurrentOption(@NotNull DiffPanelEx diffPanel) {
+    return diffPanel.getComparisonPolicy();
   }
 
-  private static class IgnoringPolicyAction extends DumbAwareAction {
+  private static class IgnoringPolicyAction extends DiffPanelAction {
     private final ComparisonPolicy myPolicy;
 
     public IgnoringPolicyAction(String text, ComparisonPolicy policy) {
@@ -90,11 +54,9 @@
       myPolicy = policy;
     }
 
-    public void actionPerformed(AnActionEvent e) {
-      final DiffPanelImpl diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
-      if (diffPanel != null) {
-        diffPanel.setComparisonPolicy(myPolicy);
-      }
+    @Override
+    protected void perform(@NotNull DiffPanelEx diffPanel) {
+      diffPanel.setComparisonPolicy(myPolicy);
     }
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/CurrentLineMarker.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/CurrentLineMarker.java
index 8d7559d..515fc9d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/CurrentLineMarker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/CurrentLineMarker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -64,4 +64,14 @@
     if (isHiden()) return;
     set();
   }
+
+  @Override
+  public void caretAdded(CaretEvent e) {
+
+  }
+
+  @Override
+  public void caretRemoved(CaretEvent e) {
+
+  }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java
index a3715fd..1ee83be 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java
@@ -19,11 +19,10 @@
 import com.intellij.openapi.diff.DiffContent;
 import com.intellij.openapi.diff.DiffContentUtil;
 import com.intellij.openapi.diff.DiffViewer;
-import com.intellij.openapi.diff.LineTokenizer;
-import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.external.DiffManagerImpl;
 import com.intellij.openapi.diff.impl.fragments.Fragment;
 import com.intellij.openapi.diff.impl.fragments.LineFragment;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.impl.util.FocusDiffSide;
 import com.intellij.openapi.diff.impl.util.TextDiffType;
 import com.intellij.openapi.editor.Document;
@@ -34,7 +33,6 @@
 import com.intellij.openapi.fileTypes.FileTypes;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.FrameWrapper;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.ImageLoader;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
@@ -47,7 +45,7 @@
   private DiffUtil() {
   }
 
-  public static void initDiffFrame(Project project, FrameWrapper frameWrapper, final DiffViewer diffPanel, final JComponent mainComponent) {
+  public static void initDiffFrame(Project project, @NotNull FrameWrapper frameWrapper, @NotNull final DiffViewer diffPanel, final JComponent mainComponent) {
     frameWrapper.setComponent(mainComponent);
     frameWrapper.setProject(project);
     frameWrapper.setImage(ImageLoader.loadFromResource("/diff/Diff.png"));
@@ -56,15 +54,17 @@
   }
 
   @Nullable
-  public static FocusDiffSide getFocusDiffSide(DataContext dataContext) {
+  public static FocusDiffSide getFocusDiffSide(@NotNull DataContext dataContext) {
     return FocusDiffSide.DATA_KEY.getData(dataContext);
   }
 
-  public static String[] convertToLines(@NotNull String text) {
-    return new LineTokenizer(text).execute();
+  @NotNull
+  public static DiffString[] convertToLines(@NotNull String text) {
+    return DiffString.create(text).tokenize();
   }
 
-  public static FileType[] chooseContentTypes(DiffContent[] contents) {
+  @NotNull
+  public static FileType[] chooseContentTypes(@NotNull DiffContent[] contents) {
     FileType commonType = FileTypes.PLAIN_TEXT;
     for (DiffContent content : contents) {
       FileType contentType = content.getContentType();
@@ -78,7 +78,7 @@
     return result;
   }
 
-  public static boolean isWritable(DiffContent content) {
+  public static boolean isWritable(@NotNull DiffContent content) {
     Document document = content.getDocument();
     return document != null && document.isWritable();
   }
@@ -92,7 +92,7 @@
     return editor;
   }
 
-  public static void drawBoldDottedFramingLines(Graphics2D g, int startX, int endX, int startY, int bottomY, Color color) {
+  public static void drawBoldDottedFramingLines(@NotNull Graphics2D g, int startX, int endX, int startY, int bottomY, @NotNull Color color) {
     UIUtil.drawBoldDottedLine(g, startX, endX, startY, null, color, false);
     UIUtil.drawBoldDottedLine(g, startX, endX, bottomY, null, color, false);
   }
@@ -102,8 +102,9 @@
     UIUtil.drawLine(g, startX, y + 1, endX, y + 1, null, color);
   }
 
-  public static Color getFramingColor(@NotNull Color backgroundColor) {
-    return backgroundColor.darker();
+  @Nullable
+  public static Color getFramingColor(@Nullable Color backgroundColor) {
+    return backgroundColor != null ? backgroundColor.darker() : null;
   }
 
   @NotNull
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/FragmentedDiffPanelState.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/FragmentedDiffPanelState.java
index d3b273f..7e395c1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/FragmentedDiffPanelState.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/FragmentedDiffPanelState.java
@@ -137,7 +137,8 @@
     //setDiffPolicy(diffPolicy);
     diffPolicy.setRanges(ranges);
 
-    return addMarkup(new TextCompareProcessor(myComparisonPolicy, diffPolicy).process(myAppender1.getText(), myAppender2.getText()));
+    return addMarkup(
+      new TextCompareProcessor(myComparisonPolicy, diffPolicy, myHighlightMode).process(myAppender1.getText(), myAppender2.getText()));
   }
 
   private BeforeAfter<Integer> lineStarts(int i) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/PresetBlocksDiffPolicy.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/PresetBlocksDiffPolicy.java
index db11ed0..3fd7df1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/PresetBlocksDiffPolicy.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/PresetBlocksDiffPolicy.java
@@ -15,11 +15,14 @@
  */
 package com.intellij.openapi.diff.impl.highlighting;
 
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.processing.DiffPolicy;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.util.BeforeAfter;
 import com.intellij.util.diff.FilesTooBigForDiffException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -33,19 +36,28 @@
 public class PresetBlocksDiffPolicy implements DiffPolicy {
   // fragment _start_ offsets
   private List<BeforeAfter<TextRange>> myRanges;
-  private final DiffPolicy myDelegate;
+  @NotNull private final DiffPolicy myDelegate;
 
-  public PresetBlocksDiffPolicy(DiffPolicy delegate) {
+  public PresetBlocksDiffPolicy(@NotNull DiffPolicy delegate) {
     myDelegate = delegate;
   }
 
+  @TestOnly
+  @NotNull
   @Override
-  public DiffFragment[] buildFragments(String text1, String text2) throws FilesTooBigForDiffException {
+  public DiffFragment[] buildFragments(@NotNull String text1, @NotNull String text2) throws FilesTooBigForDiffException {
+    return buildFragments(DiffString.create(text1), DiffString.create(text2));
+  }
+
+  @NotNull
+  @Override
+  public DiffFragment[] buildFragments(@NotNull DiffString text1, @NotNull DiffString text2) throws FilesTooBigForDiffException {
     final List<DiffFragment> fragments = new ArrayList<DiffFragment>();
     for (int i = 0; i < myRanges.size(); i++) {
       final BeforeAfter<TextRange> range = myRanges.get(i);
-      fragments.addAll(Arrays.asList(myDelegate.buildFragments(new String(text1.substring(range.getBefore().getStartOffset(), range.getBefore().getEndOffset())),
-                       new String(text2.substring(range.getAfter().getStartOffset(), range.getAfter().getEndOffset())))));
+      fragments.addAll(Arrays.asList(myDelegate.buildFragments(
+        text1.substring(range.getBefore().getStartOffset(), range.getBefore().getEndOffset()).copy(),
+        text2.substring(range.getAfter().getStartOffset(), range.getAfter().getEndOffset()).copy())));
     }
 
     return fragments.toArray(new DiffFragment[fragments.size()]);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java
index 14c2354..d3e1dfd 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java
@@ -30,8 +30,8 @@
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 
 public abstract class SimpleDiffPanelState implements Disposable  {
   protected ComparisonPolicy myComparisonPolicy = ComparisonPolicy.DEFAULT;
@@ -84,7 +84,7 @@
   public void dispose() {
   }
 
-  private LineBlocks addMarkup(final ArrayList<LineFragment> lines) {
+  private LineBlocks addMarkup(final List<LineFragment> lines) {
     ApplicationManager.getApplication().runWriteAction(new Runnable() {
       public void run() {
         final FragmentHighlighterImpl fragmentHighlighter = new FragmentHighlighterImpl(myAppender1, myAppender2);
@@ -114,12 +114,8 @@
       return LineBlocks.EMPTY;
     }
 
-    if (myHighlightMode == HighlightMode.NO_HIGHLIGHTING) {
-      return LineBlocks.fromLineFragments(Collections.<LineFragment>emptyList());
-    }
-
-    return addMarkup(new TextCompareProcessor(myComparisonPolicy, myDiffPolicy, myHighlightMode == HighlightMode.BY_WORD)
-                       .process(myAppender1.getText(), myAppender2.getText()));
+    return addMarkup(
+      new TextCompareProcessor(myComparisonPolicy, myDiffPolicy, myHighlightMode).process(myAppender1.getText(), myAppender2.getText()));
   }
 
   public Project getProject() { return myProject; }
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeList.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeList.java
index dc0e98e..bbd8c92 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeList.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeList.java
@@ -16,6 +16,7 @@
 package com.intellij.openapi.diff.impl.incrementalMerge;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
 import com.intellij.openapi.diff.impl.DiffUtil;
@@ -29,6 +30,7 @@
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashSet;
 import com.intellij.util.diff.FilesTooBigForDiffException;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.*;
 
@@ -108,12 +110,12 @@
 
   private ArrayList<Change> buildChanges() throws FilesTooBigForDiffException {
     Document base = getDocument(FragmentSide.SIDE1);
-    String[] baseLines = DiffUtil.convertToLines(base.getText());
+    DiffString[] baseLines = DiffUtil.convertToLines(base.getText());
     Document version = getDocument(FragmentSide.SIDE2);
-    String[] versionLines = DiffUtil.convertToLines(version.getText());
+    DiffString[] versionLines = DiffUtil.convertToLines(version.getText());
     DiffFragment[] fragments = ComparisonPolicy.DEFAULT.buildDiffFragmentsFromLines(baseLines, versionLines);
     final ArrayList<Change> result = new ArrayList<Change>();
-    new DiffFragmemntsEnumerator(fragments) {
+    new DiffFragmentsEnumerator(fragments) {
       protected void process(DiffFragment fragment) {
         if (fragment.isEqual()) return;
         Context context = getContext();
@@ -129,11 +131,11 @@
     return myChanges.get(index);
   }
 
-  private abstract static class DiffFragmemntsEnumerator {
+  private abstract static class DiffFragmentsEnumerator {
     private final DiffFragment[] myFragments;
     private final Context myContext;
 
-    private DiffFragmemntsEnumerator(DiffFragment[] fragments) {
+    private DiffFragmentsEnumerator(DiffFragment[] fragments) {
       myContext = new Context();
       myFragments = fragments;
     }
@@ -142,8 +144,8 @@
       for (DiffFragment fragment : myFragments) {
         myContext.myFragment = fragment;
         process(fragment);
-        String text1 = fragment.getText1();
-        String text2 = fragment.getText2();
+        DiffString text1 = fragment.getText1();
+        DiffString text2 = fragment.getText2();
         myContext.myStarts[0] += StringUtil.length(text1);
         myContext.myStarts[1] += StringUtil.length(text2);
         myContext.myLines[0] += countLines(text1);
@@ -151,7 +153,7 @@
       }
     }
 
-    private static int countLines(String text) {
+    private static int countLines(@Nullable DiffString text) {
       if (text == null) return 0;
       return StringUtil.countNewLines(text);
     }
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java
index 2c1b1e2..d3a0b5a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java
@@ -24,6 +24,7 @@
 import com.intellij.openapi.diff.DiffBundle;
 import com.intellij.openapi.diff.DiffContent;
 import com.intellij.openapi.diff.DiffRequest;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.incrementalMerge.ui.MergePanel2;
@@ -149,8 +150,8 @@
                                                  @NotNull String baseText,
                                                  @NotNull String rightText,
                                                  @NotNull ContextLogger logger) throws FilesTooBigForDiffException {
-    DiffFragment[] leftFragments = DiffPolicy.DEFAULT_LINES.buildFragments(baseText, leftText);
-    DiffFragment[] rightFragments = DiffPolicy.DEFAULT_LINES.buildFragments(baseText, rightText);
+    DiffFragment[] leftFragments = DiffPolicy.DEFAULT_LINES.buildFragments(DiffString.create(baseText), DiffString.create(leftText));
+    DiffFragment[] rightFragments = DiffPolicy.DEFAULT_LINES.buildFragments(DiffString.create(baseText), DiffString.create(rightText));
     int[] leftOffsets = {0, 0};
     int[] rightOffsets = {0, 0};
     int leftIndex = 0;
@@ -188,7 +189,7 @@
     leftOffsets[1] += versionLength;
   }
 
-  private static int getTextLength(@Nullable String text1) {
+  private static int getTextLength(@Nullable DiffString text1) {
     return text1 != null ? text1.length() : 0;
   }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/PreferWholeLines.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/PreferWholeLines.java
index 2a6a01c..2d41620 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/PreferWholeLines.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/PreferWholeLines.java
@@ -18,35 +18,47 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.util.text.StringUtil;
 
 class PreferWholeLines implements DiffCorrection {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.processing.PreferWholeLines");
   public static final DiffCorrection INSTANCE = new PreferWholeLines();
+
   public DiffFragment[] correct(DiffFragment[] fragments) {
     for (int i = 1; i < fragments.length - 1; i++) {
       DiffFragment fragment = fragments[i];
       if (!fragment.isOneSide()) continue;
       DiffFragment nextFragment = fragments[i + 1];
       FragmentSide side = FragmentSide.chooseSide(fragment);
+
+      DiffString fragmentText = side.getText(fragment);
+      DiffString otherNextFragmentText = side.getOtherText(nextFragment);
+      DiffString nextFragmentText = side.getText(nextFragment);
+
       if (nextFragment.isOneSide()) {
-        LOG.error("<" + side.getText(fragment) + "> <" + side.getOtherText(nextFragment) + ">");
+        LOG.error("<" + fragmentText + "> <" + otherNextFragmentText + ">");
       }
-      if (StringUtil.startsWithChar(side.getText(fragment), '\n') &&
-          StringUtil.startsWithChar(side.getText(nextFragment), '\n') &&
-          StringUtil.startsWithChar(side.getOtherText(nextFragment), '\n')) {
+      if (StringUtil.startsWithChar(fragmentText, '\n') &&
+          StringUtil.startsWithChar(nextFragmentText, '\n') &&
+          StringUtil.startsWithChar(otherNextFragmentText, '\n')) {
+
         DiffFragment previous = fragments[i - 1];
-        previous = side.createFragment(side.getText(previous) + "\n",
-                                       side.getOtherText(previous) + "\n",
-                                       previous.isModified());
+        DiffString previousText = side.getText(previous);
+        DiffString otherPreciousText = side.getOtherText(previous);
+
+        assert previous != null;
+        assert previousText != null;
+        assert otherPreciousText != null;
+        assert fragmentText != null;
+        assert nextFragmentText != null;
+        assert otherNextFragmentText != null;
+
+        previous = side.createFragment(previousText.append('\n'), otherPreciousText.append('\n'), previous.isModified());
         fragments[i - 1] = previous;
-        fragment = side.createFragment(side.getText(fragment).substring(1) + "\n",
-                                       side.getOtherText(fragment),
-                                       fragment.isModified());
+        fragment = side.createFragment(fragmentText.substring(1).append('\n'), side.getOtherText(fragment), fragment.isModified());
         fragments[i] = fragment;
-        nextFragment = side.createFragment(side.getText(nextFragment).substring(1),
-                                           side.getOtherText(nextFragment).substring(1),
-                                           nextFragment.isModified());
+        nextFragment = side.createFragment(nextFragmentText.substring(1), otherNextFragmentText.substring(1), nextFragment.isModified());
         fragments[i + 1] = nextFragment;
       }
     }
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/TextCompareProcessor.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/TextCompareProcessor.java
index e527964..1ae503e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/TextCompareProcessor.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/TextCompareProcessor.java
@@ -23,53 +23,59 @@
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.highlighting.LineBlockDivider;
 import com.intellij.openapi.diff.impl.highlighting.Util;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.diff.FilesTooBigForDiffException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 public class TextCompareProcessor {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.processing.Processor");
-  private final DiffPolicy myDiffPolicy;
   @NotNull private final ComparisonPolicy myComparisonPolicy;
-  private final boolean mySearchForSubFragments;
+  @NotNull private final DiffPolicy myDiffPolicy;
+  @NotNull private final HighlightMode myHighlightMode;
 
   public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy,
-                              final DiffPolicy diffPolicy,
-                              boolean searchForSubFragments) {
+                              @NotNull DiffPolicy diffPolicy,
+                              @NotNull HighlightMode highlightMode) {
     myComparisonPolicy = comparisonPolicy;
     myDiffPolicy = diffPolicy;
-    mySearchForSubFragments = searchForSubFragments;
-  }
-
-  public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy, final DiffPolicy diffPolicy) {
-    this(comparisonPolicy, diffPolicy, true);
+    myHighlightMode = highlightMode;
   }
 
   public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy) {
-    this(comparisonPolicy, DiffPolicy.LINES_WO_FORMATTING);
+    this(comparisonPolicy, DiffPolicy.LINES_WO_FORMATTING, HighlightMode.BY_WORD);
   }
 
-  public ArrayList<LineFragment> process(@Nullable String text1, @Nullable String text2) throws FilesTooBigForDiffException {
+  public List<LineFragment> process(@Nullable String text1, @Nullable String text2) throws FilesTooBigForDiffException {
+    if (myHighlightMode == HighlightMode.NO_HIGHLIGHTING) {
+      return Collections.emptyList();
+    }
+
     text1 = StringUtil.notNullize(text1);
     text2 = StringUtil.notNullize(text2);
     if (text1.isEmpty() || text2.isEmpty()) {
       return new DummyDiffFragmentsProcessor().process(text1, text2);
     }
 
-    DiffFragment[] woFormattingBlocks = myDiffPolicy.buildFragments(text1, text2);
+    DiffString diffText1 = DiffString.create(text1);
+    DiffString diffText2 = DiffString.create(text2);
+
+    DiffFragment[] woFormattingBlocks = myDiffPolicy.buildFragments(diffText1, diffText2);
     DiffFragment[] step1lineFragments = new DiffCorrection.TrueLineBlocks(myComparisonPolicy).correctAndNormalize(woFormattingBlocks);
     ArrayList<LineFragment> lineBlocks = new DiffFragmentsProcessor().process(step1lineFragments);
 
     int badLinesCount = 0;
-    if (mySearchForSubFragments) {
+    if (myHighlightMode == HighlightMode.BY_WORD) {
       for (LineFragment lineBlock : lineBlocks) {
         if (lineBlock.isOneSide() || lineBlock.isEqual()) continue;
         try {
-          String subText1 = lineBlock.getText(text1, FragmentSide.SIDE1);
-          String subText2 = lineBlock.getText(text2, FragmentSide.SIDE2);
+          DiffString subText1 = lineBlock.getText(diffText1, FragmentSide.SIDE1);
+          DiffString subText2 = lineBlock.getText(diffText2, FragmentSide.SIDE2);
           ArrayList<LineFragment> subFragments = findSubFragments(subText1, subText2);
           lineBlock.setChildren(new ArrayList<Fragment>(subFragments));
           lineBlock.adjustTypeFromChildrenTypes();
@@ -84,7 +90,7 @@
     return lineBlocks;
   }
 
-  private ArrayList<LineFragment> findSubFragments(String text1, String text2) throws FilesTooBigForDiffException {
+  private ArrayList<LineFragment> findSubFragments(@NotNull DiffString text1, @NotNull DiffString text2) throws FilesTooBigForDiffException {
     DiffFragment[] fragments = new ByWord(myComparisonPolicy).buildFragments(text1, text2);
     fragments = DiffCorrection.ConnectSingleSideToChange.INSTANCE.correct(fragments);
     fragments = UniteSameType.INSTANCE.correct(fragments);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/splitter/DividerPolygon.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/splitter/DividerPolygon.java
index 33db73f..6e6a607 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/splitter/DividerPolygon.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/splitter/DividerPolygon.java
@@ -23,6 +23,8 @@
 import com.intellij.openapi.editor.LogicalPosition;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.util.ui.GraphicsUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.awt.*;
 import java.awt.geom.CubicCurve2D;
@@ -34,7 +36,7 @@
  */
 public class DividerPolygon {
 
-  private final Color myColor;
+  @Nullable private final Color myColor;
   private final int myStart1;
   private final int myStart2;
   private final int myEnd1;
@@ -43,7 +45,7 @@
 
   public static final double CTRL_PROXIMITY_X = 0.3;
 
-  public DividerPolygon(int start1, int start2, int end1, int end2, Color color, boolean applied) {
+  public DividerPolygon(int start1, int start2, int end1, int end2, @Nullable Color color, boolean applied) {
     myApplied = applied;
     myStart1 = advance(start1);
     myStart2 = advance(start2);
@@ -150,7 +152,9 @@
     //g.setComposite(composite);
   }
 
-  public static ArrayList<DividerPolygon> createVisiblePolygons(EditingSides sides, FragmentSide left, int diffDividerPolygonsOffset) {
+  public static ArrayList<DividerPolygon> createVisiblePolygons(@NotNull EditingSides sides,
+                                                                @NotNull FragmentSide left,
+                                                                int diffDividerPolygonsOffset) {
     Editor editor1 = sides.getEditor(left);
     Editor editor2 = sides.getEditor(left.otherSide());
     LineBlocks lineBlocks = sides.getLineBlocks();
@@ -174,7 +178,10 @@
     return new FoldingTransformation(editor);
   }
 
-  private static DividerPolygon createPolygon(Transformation[] transformations, Trapezium trapezium, Color color, FragmentSide left,
+  private static DividerPolygon createPolygon(@NotNull Transformation[] transformations,
+                                              @NotNull Trapezium trapezium,
+                                              @Nullable Color color,
+                                              @NotNull FragmentSide left,
                                               int diffDividerPolygonsOffset, boolean applied) {
     Interval base1 = trapezium.getBase(left);
     Interval base2 = trapezium.getBase(left.otherSide());
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java
index e169a9c..f6cd904 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java
@@ -26,7 +26,7 @@
 import com.intellij.openapi.editor.event.VisibleAreaEvent;
 import com.intellij.openapi.editor.event.VisibleAreaListener;
 import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Pair;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import java.awt.*;
@@ -35,7 +35,7 @@
 public class SyncScrollSupport implements Disposable {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.util.SyncScrollSupport");
   private boolean myDuringVerticalScroll = false;
-  private final ArrayList<ScrollListener> myScrollers = new ArrayList<ScrollListener>();
+  @NotNull private final ArrayList<ScrollListener> myScrollers = new ArrayList<ScrollListener>();
   private boolean myEnabled = true;
 
   public void install(EditingSides[] sideContainers) {
@@ -67,34 +67,34 @@
     return myEnabled;
   }
 
-  private void install2(Editor[] editors, EditingSides[] sideContainers) {
-    addSlavesScroller(editors[0], new Pair<FragmentSide, EditingSides>(FragmentSide.SIDE1, sideContainers[0]));
-    addSlavesScroller(editors[1], new Pair<FragmentSide, EditingSides>(FragmentSide.SIDE2, sideContainers[0]));
+  private void install2(@NotNull Editor[] editors, @NotNull EditingSides[] sideContainers) {
+    addSlavesScroller(editors[0], new ScrollingContext(FragmentSide.SIDE1, sideContainers[0], FragmentSide.SIDE1));
+    addSlavesScroller(editors[1], new ScrollingContext(FragmentSide.SIDE2, sideContainers[0], FragmentSide.SIDE2));
   }
 
-  private void install3(Editor[] editors, EditingSides[] sideContainers) {
+  private void install3(@NotNull Editor[] editors, @NotNull EditingSides[] sideContainers) {
     addSlavesScroller(editors[0],
-                      new Pair<FragmentSide, EditingSides>(FragmentSide.SIDE1, sideContainers[0]),
-                      new Pair<FragmentSide, EditingSides>(FragmentSide.SIDE1, sideContainers[1]));
+                      new ScrollingContext(FragmentSide.SIDE1, sideContainers[0], FragmentSide.SIDE2),
+                      new ScrollingContext(FragmentSide.SIDE1, sideContainers[1], FragmentSide.SIDE1));
     addSlavesScroller(editors[1],
-                      new Pair<FragmentSide, EditingSides>(FragmentSide.SIDE2, sideContainers[0]),
-                      new Pair<FragmentSide, EditingSides>(FragmentSide.SIDE1, sideContainers[1]));
+                      new ScrollingContext(FragmentSide.SIDE2, sideContainers[0], FragmentSide.SIDE1),
+                      new ScrollingContext(FragmentSide.SIDE1, sideContainers[1], FragmentSide.SIDE1));
     addSlavesScroller(editors[2],
-                      new Pair<FragmentSide, EditingSides>(FragmentSide.SIDE2, sideContainers[1]),
-                      new Pair<FragmentSide, EditingSides>(FragmentSide.SIDE2, sideContainers[0]));
+                      new ScrollingContext(FragmentSide.SIDE2, sideContainers[1], FragmentSide.SIDE2),
+                      new ScrollingContext(FragmentSide.SIDE2, sideContainers[0], FragmentSide.SIDE1));
   }
 
-  private void addSlavesScroller(Editor editor, Pair<FragmentSide, EditingSides>... contexts) {
+  private void addSlavesScroller(@NotNull Editor editor, @NotNull ScrollingContext... contexts) {
     ScrollListener scroller = new ScrollListener(contexts, editor);
     scroller.install();
     myScrollers.add(scroller);
   }
 
   private class ScrollListener implements VisibleAreaListener, Disposable {
-    private Pair<FragmentSide, EditingSides>[] myScrollContexts;
-    private final Editor myEditor;
+    private ScrollingContext[] myScrollContexts;
+    @NotNull private final Editor myEditor;
 
-    public ScrollListener(Pair<FragmentSide, EditingSides>[] scrollContexts, Editor editor) {
+    public ScrollListener(@NotNull ScrollingContext[] scrollContexts, @NotNull Editor editor) {
       myScrollContexts = scrollContexts;
       myEditor = editor;
     }
@@ -103,11 +103,13 @@
       myEditor.getScrollingModel().addVisibleAreaListener(this);
     }
 
+    @Override
     public void dispose() {
       myEditor.getScrollingModel().removeVisibleAreaListener(this);
       myScrollContexts = null;
     }
 
+    @Override
     public void visibleAreaChanged(VisibleAreaEvent e) {
       if (!myEnabled || myDuringVerticalScroll) return;
       Rectangle newRectangle = e.getNewRectangle();
@@ -115,7 +117,7 @@
       if (newRectangle == null || oldRectangle == null) return;
       myDuringVerticalScroll = true;
       try {
-        for (Pair<FragmentSide, EditingSides> context : myScrollContexts) {
+        for (ScrollingContext context : myScrollContexts) {
           syncVerticalScroll(context, newRectangle, oldRectangle);
           syncHorizontalScroll(context, newRectangle, oldRectangle);
         }
@@ -124,11 +126,13 @@
     }
   }
 
-  private static void syncHorizontalScroll(Pair<FragmentSide,EditingSides> context, Rectangle newRectangle, Rectangle oldRectangle) {
+  private static void syncHorizontalScroll(@NotNull ScrollingContext context,
+                                           @NotNull Rectangle newRectangle,
+                                           @NotNull Rectangle oldRectangle) {
     int newScrollOffset = newRectangle.x;
     if (newScrollOffset == oldRectangle.x) return;
-    EditingSides sidesContainer = context.getSecond();
-    FragmentSide masterSide = context.getFirst();
+    EditingSides sidesContainer = context.getSidesContainer();
+    FragmentSide masterSide = context.getMasterSide();
     Editor slaveEditor = sidesContainer.getEditor(masterSide.otherSide());
     if (slaveEditor == null) return;
 
@@ -138,10 +142,13 @@
     scrollingModel.enableAnimation();
   }
 
-  private static void syncVerticalScroll(Pair<FragmentSide,EditingSides> context, Rectangle newRectangle, Rectangle oldRectangle) {
+  private static void syncVerticalScroll(@NotNull ScrollingContext context,
+                                         @NotNull Rectangle newRectangle,
+                                         @NotNull Rectangle oldRectangle) {
     if (newRectangle.y == oldRectangle.y && newRectangle.height == oldRectangle.height) return;
-    EditingSides sidesContainer = context.getSecond();
-    FragmentSide masterSide = context.getFirst();
+    EditingSides sidesContainer = context.getSidesContainer();
+    FragmentSide masterSide = context.getMasterSide();
+    FragmentSide masterDiffSide = context.getMasterDiffSide();
 
     Editor master = sidesContainer.getEditor(masterSide);
     Editor slave = sidesContainer.getEditor(masterSide.otherSide());
@@ -159,7 +166,7 @@
     if (masterCenterLine > master.getDocument().getLineCount()) {
       masterCenterLine = master.getDocument().getLineCount();
     }
-    int scrollToLine = sidesContainer.getLineBlocks().transform(masterSide, masterCenterLine) + 1;
+    int scrollToLine = sidesContainer.getLineBlocks().transform(masterDiffSide, masterCenterLine) + 1;
     int actualLine = scrollToLine - 1;
 
 
@@ -179,18 +186,45 @@
     }
   }
 
-  private static int getScrollOffset(final Editor editor) {
+  private static int getScrollOffset(@NotNull final Editor editor) {
     final JComponent header = editor.getHeaderComponent();
     int headerOffset = header == null ? 0 : header.getHeight();
     
     return editor.getScrollingModel().getVerticalScrollOffset() - headerOffset;
   }
 
-  public static void scrollEditor(Editor editor, int logicalLine) {
+  public static void scrollEditor(@NotNull Editor editor, int logicalLine) {
     editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(logicalLine, 0));
     ScrollingModel scrollingModel = editor.getScrollingModel();
     scrollingModel.disableAnimation();
     scrollingModel.scrollToCaret(ScrollType.CENTER);
     scrollingModel.enableAnimation();
   }
+
+  private static class ScrollingContext {
+    @NotNull private final EditingSides mySidesContainer;
+    @NotNull private final FragmentSide myMasterSide;
+    @NotNull private final FragmentSide myMasterDiffSide;
+
+    public ScrollingContext(@NotNull FragmentSide masterSide, @NotNull EditingSides sidesContainer, @NotNull FragmentSide masterDiffSide) {
+      mySidesContainer = sidesContainer;
+      myMasterSide = masterSide;
+      myMasterDiffSide = masterDiffSide;
+    }
+
+    @NotNull
+    public EditingSides getSidesContainer() {
+      return mySidesContainer;
+    }
+
+    @NotNull
+    public FragmentSide getMasterSide() {
+      return myMasterSide;
+    }
+
+    @NotNull
+    public FragmentSide getMasterDiffSide() {
+      return myMasterDiffSide;
+    }
+  }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutAction.java
index 4fc378e..dd54b1d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutAction.java
@@ -53,12 +53,7 @@
         });
       }
       editor.getSelectionModel().copySelectionToClipboard();
-      editor.getCaretModel().runForEachCaret(new CaretAction() {
-        @Override
-        public void perform(Caret caret) {
-          EditorModificationUtil.deleteSelectedText(editor);
-        }
-      });
+      EditorModificationUtil.deleteSelectedTextForAllCarets(editor);
     }
   }
 }
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EscapeAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EscapeAction.java
index 16b6676..bc3b85b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EscapeAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EscapeAction.java
@@ -50,7 +50,7 @@
     public boolean isEnabled(Editor editor, DataContext dataContext) {
       SelectionModel selectionModel = editor.getSelectionModel();
       CaretModel caretModel = editor.getCaretModel();
-      return selectionModel.hasSelection() || selectionModel.hasBlockSelection() || caretModel.getAllCarets().size() > 1;
+      return selectionModel.hasSelection() || selectionModel.hasBlockSelection() || caretModel.getCaretCount() > 1;
     }
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftOrRightHandler.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftOrRightHandler.java
index 1883cb5..182884b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftOrRightHandler.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftOrRightHandler.java
@@ -49,13 +49,19 @@
         int start = selectionModel.getSelectionStart();
         int end = selectionModel.getSelectionEnd();
         int caretOffset = caretModel.getOffset();
+        VisualPosition targetPosition = myDirection == Direction.RIGHT ? selectionModel.getSelectionEndPosition() : selectionModel.getSelectionStartPosition();
 
         //int leftGuard = start + (myDirection == Direction.LEFT ? 1 : 0);
         //int rightGuard = end - (myDirection == Direction.RIGHT ? 1 : 0);
         //if (TextRange.from(leftGuard, rightGuard - leftGuard + 1).contains(caretModel.getOffset())) { // See IDEADEV-36957
         if (start <= caretOffset && end >= caretOffset) { // See IDEADEV-36957
           selectionModel.removeSelection();
-          caretModel.moveToOffset(myDirection == Direction.RIGHT ? end : start);
+          if (caretModel.supportsMultipleCarets() && editor.isColumnMode() && targetPosition != null) {
+            caretModel.moveToVisualPosition(targetPosition);
+          }
+          else {
+            caretModel.moveToOffset(myDirection == Direction.RIGHT ? end : start);
+          }
           scrollingModel.scrollToCaret(ScrollType.RELATIVE);
           return;
         }
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
index 012410d..41a833b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
@@ -806,6 +806,15 @@
     int line = y / editor.getLineHeight();
     return line > 0 ? editor.visualToLogicalPosition(new VisualPosition(line, 0)).line : 0;
   }
+
+  public static boolean isAtLineEnd(@NotNull Editor editor, int offset) {
+    Document document = editor.getDocument();
+    if (offset < 0 || offset > document.getTextLength()) {
+      return false;
+    }
+    int line = document.getLineNumber(offset);
+    return offset == document.getLineEndOffset(line);
+  }
 }
 
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
index 1b79d35..f6f030c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
@@ -94,6 +94,10 @@
   private int startBefore;
   private int endBefore;
   boolean myUnknownDirection;
+  // offsets of selection start/end position relative to end of line - can be non-zero in column selection mode
+  // these are non-negative values, myStartVirtualOffset is always less or equal to myEndVirtualOffset
+  private int myStartVirtualOffset;
+  private int myEndVirtualOffset;
 
   CaretImpl(EditorImpl editor) {
     myEditor = editor;
@@ -144,10 +148,18 @@
       if (marker.isValid()) {
         startAfter = marker.getStartOffset();
         endAfter = marker.getEndOffset();
+        if (myEndVirtualOffset > 0 && (!isVirtualSelectionEnabled()
+                                       || !EditorUtil.isAtLineEnd(myEditor, endAfter)
+                                       || myEditor.getDocument().getLineNumber(startAfter) != myEditor.getDocument().getLineNumber(endAfter))) {
+          myStartVirtualOffset = 0;
+          myEndVirtualOffset = 0;
+        }
       }
       else {
         startAfter = endAfter = getOffset();
         marker.release();
+        myStartVirtualOffset = 0;
+        myEndVirtualOffset = 0;
         mySelectionMarker = null;
       }
 
@@ -235,7 +247,8 @@
     myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
       public void run() {
         SelectionModelImpl selectionModel = myEditor.getSelectionModel();
-        final int leadSelectionOffset = selectionModel.getLeadSelectionOffset();
+        final int leadSelectionOffset = getLeadSelectionOffset();
+        final VisualPosition leadSelectionPosition = getLeadSelectionPosition();
         LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
                                               ? selectionModel.getBlockStart()
                                               : getLogicalPosition();
@@ -349,24 +362,43 @@
           }
           else {
             if (selectToDocumentStart) {
-              selectionModel.setSelection(leadSelectionOffset, 0);
+              if (myEditor.getCaretModel().supportsMultipleCarets()) {
+                setSelection(leadSelectionPosition, leadSelectionOffset, myEditor.offsetToVisualPosition(0), 0);
+              }
+              else {
+                setSelection(leadSelectionOffset, 0);
+              }
             }
             else if (pos.line >= myEditor.getVisibleLineCount()) {
-              if (leadSelectionOffset < document.getTextLength()) {
-                selectionModel.setSelection(leadSelectionOffset, document.getTextLength());
+              int endOffset = document.getTextLength();
+              if (leadSelectionOffset < endOffset) {
+                if (myEditor.getCaretModel().supportsMultipleCarets()) {
+                  setSelection(leadSelectionPosition, leadSelectionOffset, myEditor.offsetToVisualPosition(endOffset), endOffset);
+                }
+                else {
+                  setSelection(leadSelectionOffset, endOffset);
+                }
               }
             }
             else {
               int selectionStartToUse = leadSelectionOffset;
-              if (selectionModel.isUnknownDirection()) {
-                if (getOffset() > leadSelectionOffset) {
-                  selectionStartToUse = Math.min(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
+              VisualPosition selectionStartPositionToUse = leadSelectionPosition;
+              if (isUnknownDirection()) {
+                if (getOffset() > leadSelectionOffset ^ getSelectionStart() < getSelectionEnd()) {
+                  selectionStartToUse = getSelectionEnd();
+                  selectionStartPositionToUse = getSelectionEndPosition();
                 }
                 else {
-                  selectionStartToUse = Math.max(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
+                  selectionStartToUse = getSelectionStart();
+                  selectionStartPositionToUse = getSelectionStartPosition();
                 }
               }
-              selectionModel.setSelection(selectionStartToUse, getVisualPosition(), getOffset());
+              if (myEditor.getCaretModel().supportsMultipleCarets()) {
+                setSelection(selectionStartPositionToUse, selectionStartToUse, getVisualPosition(), getOffset());
+              }
+              else {
+                setSelection(selectionStartToUse, getVisualPosition(), getOffset());
+              }
             }
           }
         }
@@ -933,22 +965,32 @@
     int lineShift = above ? -1 : 1;
     final CaretImpl clone = cloneWithoutSelection();
     final int newSelectionStartOffset, newSelectionEndOffset;
+    final VisualPosition newSelectionStartPosition, newSelectionEndPosition;
     final boolean hasNewSelection;
     if (hasSelection()) {
-      LogicalPosition selectionStart = myEditor.offsetToLogicalPosition(getSelectionStart());
-      LogicalPosition selectionEnd = myEditor.offsetToLogicalPosition(getSelectionEnd());
-      LogicalPosition newSelectionStart = new LogicalPosition(selectionStart.line + lineShift, selectionStart.column);
-      LogicalPosition newSelectionEnd = new LogicalPosition(selectionEnd.line + lineShift, selectionEnd.column);
-      newSelectionStartOffset = getTruncatedOffset(newSelectionStart);
-      newSelectionEndOffset = getTruncatedOffset(newSelectionEnd);
-      hasNewSelection = newSelectionStartOffset != newSelectionEndOffset;
+      VisualPosition startPosition = getSelectionStartPosition();
+      VisualPosition endPosition = getSelectionEndPosition();
+      VisualPosition leadPosition = getLeadSelectionPosition();
+      boolean leadIsStart = leadPosition.equals(startPosition);
+      boolean leadIsEnd = leadPosition.equals(endPosition);
+      LogicalPosition selectionStart = myEditor.visualToLogicalPosition(leadIsStart || leadIsEnd ? leadPosition : startPosition);
+      LogicalPosition selectionEnd = myEditor.visualToLogicalPosition(leadIsEnd ? startPosition : endPosition);
+      LogicalPosition newSelectionStart = truncate(new LogicalPosition(selectionStart.line + lineShift, selectionStart.column));
+      LogicalPosition newSelectionEnd = truncate(new LogicalPosition(selectionEnd.line + lineShift, selectionEnd.column));
+      newSelectionStartOffset = myEditor.logicalPositionToOffset(newSelectionStart);
+      newSelectionEndOffset = myEditor.logicalPositionToOffset(newSelectionEnd);
+      newSelectionStartPosition = myEditor.logicalToVisualPosition(newSelectionStart);
+      newSelectionEndPosition = myEditor.logicalToVisualPosition(newSelectionEnd);
+      hasNewSelection = !newSelectionStart.equals(newSelectionEnd);
     }
     else {
       newSelectionStartOffset = 0;
       newSelectionEndOffset = 0;
+      newSelectionStartPosition = null;
+      newSelectionEndPosition = null;
       hasNewSelection = false;
     }
-    LogicalPosition oldPosition = hasSelection() && !hasNewSelection ? myEditor.offsetToLogicalPosition(getSelectionStart()) : getLogicalPosition();
+    LogicalPosition oldPosition = getLogicalPosition();
     int newLine = oldPosition.line + lineShift;
     if (newLine < 0 || newLine >= myEditor.getDocument().getLineCount()) {
       Disposer.dispose(clone);
@@ -956,11 +998,11 @@
     }
     clone.moveToLogicalPosition(new LogicalPosition(newLine, oldPosition.column), false, null, false);
     if (myEditor.getCaretModel().addCaret(clone)) {
-      if (hasSelection() && hasNewSelection) {
+      if (hasNewSelection) {
         myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
           @Override
           public void run() {
-            clone.setSelection(Math.min(newSelectionStartOffset, newSelectionEndOffset), Math.max(newSelectionStartOffset, newSelectionEndOffset));
+            clone.setSelection(newSelectionStartPosition, newSelectionStartOffset, newSelectionEndPosition, newSelectionEndOffset);
           }
         });
         if (!clone.isValid()) {
@@ -976,15 +1018,15 @@
     }
   }
 
-  private int getTruncatedOffset(LogicalPosition position) {
+  private LogicalPosition truncate(LogicalPosition position) {
     if (position.line < 0) {
-      return 0;
+      return new LogicalPosition(0, 0);
     }
     else if (position.line >= myEditor.getDocument().getLineCount()) {
-      return myEditor.getDocument().getTextLength();
+      return myEditor.offsetToLogicalPosition(myEditor.getDocument().getTextLength());
     }
     else {
-      return myEditor.logicalPositionToOffset(position);
+      return position;
     }
   }
 
@@ -1029,18 +1071,21 @@
   @NotNull
   @Override
   public VisualPosition getSelectionStartPosition() {
-    VisualPosition defaultPosition = myEditor.offsetToVisualPosition(getSelectionStart());
-    if (!hasSelection()) {
-      return defaultPosition;
+    validateContext(false);
+    VisualPosition position;
+    if (hasSelection() && mySelectionMarker != null) {
+      position = mySelectionMarker.getStartPosition();
+      if (position == null) {
+        position = myEditor.offsetToVisualPosition(mySelectionMarker.getStartOffset());
+      }
     }
-
-    MyRangeMarker marker = mySelectionMarker;
-    if (marker == null) {
-      return defaultPosition;
+    else {
+      position = isVirtualSelectionEnabled() ? getVisualPosition() : myEditor.offsetToVisualPosition(getOffset());
     }
-
-    VisualPosition result = marker.getStartPosition();
-    return result == null ? defaultPosition : result;
+    if (hasVirtualSelection()) {
+      position = new VisualPosition(position.line, position.column + myStartVirtualOffset);
+    }
+    return position;
   }
 
   @Override
@@ -1058,25 +1103,29 @@
   @NotNull
   @Override
   public VisualPosition getSelectionEndPosition() {
-    VisualPosition defaultPosition = myEditor.offsetToVisualPosition(getSelectionEnd());
-    if (!hasSelection()) {
-      return defaultPosition;
+    validateContext(false);
+    VisualPosition position;
+    if (hasSelection() && mySelectionMarker != null) {
+      position = mySelectionMarker.getEndPosition();
+      if (position == null) {
+        position = myEditor.offsetToVisualPosition(mySelectionMarker.getEndOffset());
+      }
     }
-
-    MyRangeMarker marker = mySelectionMarker;
-    if (marker == null) {
-      return defaultPosition;
+    else {
+      position = isVirtualSelectionEnabled() ? getVisualPosition() : myEditor.offsetToVisualPosition(getOffset());
     }
-
-    VisualPosition result = marker.getEndPosition();
-    return result == null ? defaultPosition : result;
+    if (hasVirtualSelection()) {
+      position = new VisualPosition(position.line, position.column + myEndVirtualOffset);
+    }
+    return position;
   }
 
   @Override
   public boolean hasSelection() {
     validateContext(false);
     MyRangeMarker marker = mySelectionMarker;
-    return marker != null && marker.isValid() && marker.getEndOffset() > marker.getStartOffset();
+    return marker != null && marker.isValid() && (marker.getEndOffset() > marker.getStartOffset()
+                                                  || isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset);
   }
 
   @Override
@@ -1162,10 +1211,12 @@
         }
 
     /* Normalize selection */
+        boolean switchedOffsets = false;
         if (startOffset > endOffset) {
           int tmp = startOffset;
           startOffset = endOffset;
           endOffset = tmp;
+          switchedOffsets = true;
         }
 
         FoldingModelEx foldingModel = myEditor.getFoldingModel();
@@ -1200,6 +1251,8 @@
         }
 
         marker = new MyRangeMarker((DocumentEx)doc, startOffset, endOffset);
+        myStartVirtualOffset = 0;
+        myEndVirtualOffset = 0;
         if (visualPositionAware) {
           if (endPosition.after(startPosition)) {
             marker.setStartPosition(startPosition);
@@ -1211,6 +1264,17 @@
             marker.setEndPosition(startPosition);
             marker.setEndPositionIsLead(true);
           }
+
+          if (isVirtualSelectionEnabled() &&
+              myEditor.getDocument().getLineNumber(startOffset) == myEditor.getDocument().getLineNumber(endOffset)) {
+            int endLineColumn = myEditor.offsetToVisualPosition(endOffset).column;
+            int startDiff =
+              EditorUtil.isAtLineEnd(myEditor, switchedOffsets ? endOffset : startOffset) ? startPosition.column - endLineColumn : 0;
+            int endDiff =
+              EditorUtil.isAtLineEnd(myEditor, switchedOffsets ? startOffset : endOffset) ? endPosition.column - endLineColumn : 0;
+            myStartVirtualOffset = Math.max(0, Math.min(startDiff, endDiff));
+            myEndVirtualOffset = Math.max(0, Math.max(startDiff, endDiff));
+          }
         }
         mySelectionMarker = marker;
 
@@ -1248,6 +1312,8 @@
           int endOffset = marker.getEndOffset();
           marker.release();
           mySelectionMarker = null;
+          myStartVirtualOffset = 0;
+          myEndVirtualOffset = 0;
           myEditor.getSelectionModel().fireSelectionChanged(startOffset, endOffset, caretOffset, caretOffset);
         }
       }
@@ -1293,17 +1359,36 @@
   public VisualPosition getLeadSelectionPosition() {
     MyRangeMarker marker = mySelectionMarker;
     VisualPosition caretPosition = getVisualPosition();
+    if (isVirtualSelectionEnabled() && !hasSelection()) {
+      return caretPosition;
+    }
     if (marker == null) {
       return caretPosition;
     }
 
     if (marker.isEndPositionIsLead()) {
       VisualPosition result = marker.getEndPosition();
-      return result == null ? getSelectionEndPosition() : result;
+      if (result == null) {
+        return getSelectionEndPosition();
+      }
+      else {
+        if (hasVirtualSelection()) {
+          result = new VisualPosition(result.line, result.column + myEndVirtualOffset);
+        }
+        return result;
+      }
     }
     else {
       VisualPosition result = marker.getStartPosition();
-      return result == null ? getSelectionStartPosition() : result;
+      if (result == null) {
+        return getSelectionStartPosition();
+      }
+      else {
+        if (hasVirtualSelection()) {
+          result = new VisualPosition(result.line, result.column + myStartVirtualOffset);
+        }
+        return result;
+      }
     }
   }
 
@@ -1367,6 +1452,16 @@
     }
   }
 
+  private boolean isVirtualSelectionEnabled() {
+    return myEditor.isColumnMode() && myEditor.getCaretModel().supportsMultipleCarets();
+  }
+
+  boolean hasVirtualSelection() {
+    validateContext(false);
+    MyRangeMarker marker = mySelectionMarker;
+    return marker != null && marker.isValid() && isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset;
+  }
+
   /**
    * Encapsulates information about target vertical range info - its <code>'y'</code> coordinate and height in pixels.
    */
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java
index 72de1c9..ad9e08d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java
@@ -31,13 +31,11 @@
 import com.intellij.openapi.editor.event.CaretEvent;
 import com.intellij.openapi.editor.event.CaretListener;
 import com.intellij.openapi.editor.event.DocumentEvent;
-import com.intellij.openapi.editor.event.MultipleCaretListener;
 import com.intellij.openapi.editor.ex.DocumentBulkUpdateListener;
 import com.intellij.openapi.editor.ex.PrioritizedDocumentListener;
 import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
 import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Segment;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.util.EventDispatcher;
 import org.jetbrains.annotations.NotNull;
@@ -48,8 +46,7 @@
 public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, Disposable {
   private final EditorImpl myEditor;
   
-  private final EventDispatcher<MultipleCaretListener> myCaretListeners = EventDispatcher.create(MultipleCaretListener.class);
-  private final Map<CaretListener, MultipleCaretListener> myListenerMap = new HashMap<CaretListener, MultipleCaretListener>();
+  private final EventDispatcher<CaretListener> myCaretListeners = EventDispatcher.create(CaretListener.class);
   private final boolean mySupportsMultipleCarets = Registry.is("editor.allow.multiple.carets");
 
   private TextAttributes myTextAttributes;
@@ -202,38 +199,12 @@
 
   @Override
   public void addCaretListener(@NotNull final CaretListener listener) {
-    MultipleCaretListener newListener;
-    if (listener instanceof MultipleCaretListener) {
-      newListener = (MultipleCaretListener)listener;
-    }
-    else {
-      newListener = new MultipleCaretListener() {
-        @Override
-        public void caretAdded(CaretEvent e) {
-
-        }
-
-        @Override
-        public void caretRemoved(CaretEvent e) {
-
-        }
-
-        @Override
-        public void caretPositionChanged(CaretEvent e) {
-          listener.caretPositionChanged(e);
-        }
-      };
-    }
-    myListenerMap.put(listener, newListener);
-    myCaretListeners.addListener(newListener);
+    myCaretListeners.addListener(listener);
   }
 
   @Override
   public void removeCaretListener(@NotNull CaretListener listener) {
-    MultipleCaretListener newListener = myListenerMap.remove(listener);
-    if (newListener != null) {
-      myCaretListeners.removeListener(newListener);
-    }
+    myCaretListeners.removeListener(listener);
   }
 
   @Override
@@ -270,6 +241,13 @@
   }
 
   @Override
+  public int getCaretCount() {
+    synchronized (myCarets) {
+      return myCarets.size();
+    }
+  }
+
+  @Override
   @NotNull
   public List<Caret> getAllCarets() {
     List<Caret> carets;
@@ -403,8 +381,7 @@
       }
       CaretImpl currCaret = it.next();
       if (prevCaret != null && (currCaret.getVisualPosition().equals(prevCaret.getVisualPosition())
-                                || regionsIntersect(currCaret.getSelectionStart(), currCaret.getSelectionEnd(),
-                                                    prevCaret.getSelectionStart(), prevCaret.getSelectionEnd()))) {
+                                || selectionsIntersect(currCaret, prevCaret))) {
         int newSelectionStart = Math.min(currCaret.getSelectionStart(), prevCaret.getSelectionStart());
         int newSelectionEnd = Math.max(currCaret.getSelectionEnd(), prevCaret.getSelectionEnd());
         CaretImpl toRetain, toRemove;
@@ -429,10 +406,12 @@
     }
   }
 
-  private static boolean regionsIntersect(int firstStart, int firstEnd, int secondStart, int secondEnd) {
-    return firstStart < secondStart && firstEnd > secondStart
-      || firstStart > secondStart && firstStart < secondEnd
-      || firstStart == secondStart && secondEnd > secondStart && firstEnd > firstStart;
+  private static boolean selectionsIntersect(CaretImpl firstCaret, CaretImpl secondCaret) {
+    return firstCaret.getSelectionStart() < secondCaret.getSelectionStart() && firstCaret.getSelectionEnd() > secondCaret.getSelectionStart()
+      || firstCaret.getSelectionStart() > secondCaret.getSelectionStart() && firstCaret.getSelectionStart() < secondCaret.getSelectionEnd()
+      || firstCaret.getSelectionStart() == secondCaret.getSelectionStart() && secondCaret.getSelectionEnd() > secondCaret.getSelectionStart() && firstCaret.getSelectionEnd() > firstCaret.getSelectionStart()
+      || (firstCaret.getSelectionStart() == firstCaret.getSelectionEnd() && firstCaret.hasVirtualSelection() || secondCaret.getSelectionStart() == secondCaret.getSelectionEnd() && secondCaret.hasVirtualSelection())
+         && (firstCaret.getSelectionStart() == secondCaret.getSelectionStart() || firstCaret.getSelectionEnd() == secondCaret.getSelectionEnd());
   }
 
   void doWithCaretMerging(Runnable runnable) {
@@ -452,21 +431,17 @@
   }
 
   @Override
-  public void setCaretsAndSelections(@NotNull final List<LogicalPosition> caretPositions, @NotNull final List<? extends Segment> selections) {
+  public void setCaretsAndSelections(@NotNull final List<CaretState> caretStates) {
     myEditor.assertIsDispatchThread();
-    if (caretPositions.isEmpty()) {
+    if (caretStates.isEmpty()) {
       throw new IllegalArgumentException("At least one caret should exist");
     }
-    if (caretPositions.size() != selections.size()) {
-      throw new IllegalArgumentException("Position and selection lists are of different size");
-    }
     doWithCaretMerging(new Runnable() {
       public void run() {
         int index = 0;
         int oldCaretCount = myCarets.size();
         Iterator<CaretImpl> caretIterator = myCarets.iterator();
-        Iterator<? extends Segment> selectionIterator = selections.iterator();
-        for (LogicalPosition caretPosition : caretPositions) {
+        for (CaretState caretState : caretStates) {
           CaretImpl caret;
           boolean caretAdded;
           if (index++ < oldCaretCount) {
@@ -475,8 +450,8 @@
           }
           else {
             caret = new CaretImpl(myEditor);
-            if (caretPosition != null) {
-              caret.moveToLogicalPosition(caretPosition, false, null, false);
+            if (caretState != null && caretState.getCaretPosition() != null) {
+              caret.moveToLogicalPosition(caretState.getCaretPosition(), false, null, false);
             }
             synchronized (myCarets) {
               myCarets.add(caret);
@@ -484,15 +459,16 @@
             fireCaretAdded(caret);
             caretAdded = true;
           }
-          if (caretPosition != null && !caretAdded) {
-            caret.moveToLogicalPosition(caretPosition);
+          if (caretState != null && caretState.getCaretPosition() != null && !caretAdded) {
+            caret.moveToLogicalPosition(caretState.getCaretPosition());
           }
-          Segment selection = selectionIterator.next();
-          if (selection != null) {
-            caret.setSelection(selection.getStartOffset(), selection.getEndOffset());
+          if (caretState != null && caretState.getSelectionStart() != null && caretState.getSelectionEnd() != null) {
+            caret.setSelection(myEditor.logicalToVisualPosition(caretState.getSelectionStart()), myEditor.logicalPositionToOffset(caretState.getSelectionStart()),
+                               myEditor.logicalToVisualPosition(caretState.getSelectionEnd()), myEditor.logicalPositionToOffset(
+              caretState.getSelectionEnd()));
           }
         }
-        int caretsToRemove = myCarets.size() - caretPositions.size();
+        int caretsToRemove = myCarets.size() - caretStates.size();
         for (int i = 0; i < caretsToRemove; i++) {
           CaretImpl caret;
           synchronized (myCarets) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java
index e658e24..611a7c2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java
@@ -132,7 +132,14 @@
 
   @NotNull
   public Document createDocument(boolean allowUpdatesWithoutWriteAction) {
-    DocumentImpl document = new DocumentImpl("",allowUpdatesWithoutWriteAction);
+    DocumentImpl document = new DocumentImpl("", allowUpdatesWithoutWriteAction);
+    myEditorEventMulticaster.registerDocument(document);
+    return document;
+  }
+
+  @NotNull
+  public Document createDocument(@NotNull CharSequence text, boolean acceptsSlashR, boolean allowUpdatesWithoutWriteAction) {
+    DocumentImpl document = new DocumentImpl(text, acceptsSlashR, allowUpdatesWithoutWriteAction);
     myEditorEventMulticaster.registerDocument(document);
     return document;
   }
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
index 33cebb5..c003d7b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
@@ -58,6 +58,7 @@
 import com.intellij.util.Function;
 import com.intellij.util.IconUtil;
 import com.intellij.util.NullableFunction;
+import com.intellij.util.SmartList;
 import com.intellij.util.containers.Convertor;
 import com.intellij.util.containers.HashMap;
 import com.intellij.util.ui.UIUtil;
@@ -401,7 +402,7 @@
     return myBackgroundColor;
   }
 
-  private boolean isDistractionFreeMode() {
+  private static boolean isDistractionFreeMode() {
     return Registry.is("editor.distraction.free.mode");
   }
 
@@ -469,9 +470,7 @@
     int patchedStartOffset = startOffset < docLength ? document.getLineStartOffset(document.getLineNumber(startOffset)) : docLength;
     int patchedEndOffset = endOffset <= docLength ? document.getLineEndOffset(document.getLineNumber(endOffset)) + 1 : docLength;
     DisposableIterator<RangeHighlighterEx> docHighlighters = docMarkup.overlappingIterator(patchedStartOffset, patchedEndOffset);
-
-    final MarkupModelEx editorMarkup = (MarkupModelEx)myEditor.getMarkupModel();
-    DisposableIterator<RangeHighlighterEx> editorHighlighters = editorMarkup.overlappingIterator(startOffset, endOffset);
+    DisposableIterator<RangeHighlighterEx> editorHighlighters = myEditor.getMarkupModel().overlappingIterator(startOffset, endOffset);
 
     try {
       RangeHighlighterEx lastDocHighlighter = null;
@@ -504,7 +503,6 @@
         if (lastDocHighlighter == null && lastEditorHighlighter == null) return;
 
         final RangeHighlighterEx lowerHighlighter;
-
         if (less(lastDocHighlighter, lastEditorHighlighter)) {
           lowerHighlighter = lastDocHighlighter;
           lastDocHighlighter = null;
@@ -600,23 +598,23 @@
     }
   }
 
-  private TIntObjectHashMap<ArrayList<GutterMark>> myLineToGutterRenderers;
+  private TIntObjectHashMap<List<GutterMark>> myLineToGutterRenderers;
 
   private void calcIconAreaWidth() {
-    myLineToGutterRenderers = new TIntObjectHashMap<ArrayList<GutterMark>>();
+    myLineToGutterRenderers = new TIntObjectHashMap<List<GutterMark>>();
 
     processRangeHighlighters(0, myEditor.getDocument().getTextLength(), new RangeHighlighterProcessor() {
       @Override
       public void process(RangeHighlighter highlighter) {
         GutterMark renderer = highlighter.getGutterIconRenderer();
-        if (renderer == null) return;
+        if (renderer == null) {
+          return;
+        }
 
-        int startOffset = highlighter.getStartOffset();
-        int line = myEditor.getDocument().getLineNumber(startOffset);
-
-        ArrayList<GutterMark> renderers = myLineToGutterRenderers.get(line);
+        int line = myEditor.getDocument().getLineNumber(highlighter.getStartOffset());
+        List<GutterMark> renderers = myLineToGutterRenderers.get(line);
         if (renderers == null) {
-          renderers = new ArrayList<GutterMark>();
+          renderers = new SmartList<GutterMark>();
           myLineToGutterRenderers.put(line, renderers);
         }
 
@@ -628,9 +626,9 @@
 
     myIconsAreaWidth = START_ICON_AREA_WIDTH;
 
-    myLineToGutterRenderers.forEachValue(new TObjectProcedure<ArrayList<GutterMark>>() {
+    myLineToGutterRenderers.forEachValue(new TObjectProcedure<List<GutterMark>>() {
       @Override
-      public boolean execute(ArrayList<GutterMark> renderers) {
+      public boolean execute(List<GutterMark> renderers) {
         int width = 1;
         for (int i = 0; i < renderers.size(); i++) {
           GutterMark renderer = renderers.get(i);
@@ -677,7 +675,7 @@
       public boolean execute(int line) {
         if (firstVisibleLine > line || lastVisibleLine < line) return true;
         if (isLineCollapsed(line)) return true;
-        ArrayList<GutterMark> renderers = myLineToGutterRenderers.get(line);
+        List<GutterMark> renderers = myLineToGutterRenderers.get(line);
         paintIconRow(line, renderers, g);
         return true;
       }
@@ -690,7 +688,7 @@
     return region != null && region.getEndOffset() >= myEditor.getDocument().getLineEndOffset(line);
   }
 
-  private void paintIconRow(int line, ArrayList<GutterMark> row, final Graphics g) {
+  private void paintIconRow(int line, List<GutterMark> row, final Graphics g) {
     processIconsRow(line, row, new LineGutterIconRendererProcessor() {
       @Override
       public void process(int x, int y, GutterMark renderer) {
@@ -743,7 +741,7 @@
     void process(int x, int y, GutterMark renderer);
   }
 
-  private void processIconsRow(int line, ArrayList<GutterMark> row, LineGutterIconRendererProcessor processor) {
+  private void processIconsRow(int line, List<GutterMark> row, LineGutterIconRendererProcessor processor) {
     int middleCount = 0;
     int middleSize = 0;
     int x = getLineMarkerAreaOffset() + 1;
@@ -1119,7 +1117,7 @@
     if (toolTip != null && !toolTip.isEmpty()) {
       final Ref<Point> t = new Ref<Point>(e.getPoint());
       int line = EditorUtil.yPositionToLogicalLine(myEditor, e);
-      ArrayList<GutterMark> row = myLineToGutterRenderers.get(line);
+      List<GutterMark> row = myLineToGutterRenderers.get(line);
       Balloon.Position ballPosition = Balloon.Position.atRight;
       if (row != null) {
         final TreeMap<Integer, GutterMark> xPos = new TreeMap<Integer, GutterMark>();
@@ -1421,8 +1419,10 @@
   private GutterMark getGutterRenderer(final Point p) {
     int line = convertPointToLineNumber(p);
     if (line == -1) return null;
-    ArrayList<GutterMark> renderers = myLineToGutterRenderers.get(line);
-    if (renderers == null) return null;
+    List<GutterMark> renderers = myLineToGutterRenderers.get(line);
+    if (renderers == null) {
+      return null;
+    }
 
     final GutterMark[] result = {null};
     processIconsRow(line, renderers, new LineGutterIconRendererProcessor() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
index aa04b48..8b41929 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
@@ -393,7 +393,7 @@
     myFoldingModel.addListener(mySoftWrapModel, myCaretModel);
 
     myIndentsModel = new IndentsModelImpl(this);
-    myCaretModel.addCaretListener(new MultipleCaretListener() {
+    myCaretModel.addCaretListener(new CaretListener() {
       @Nullable private LightweightHint myCurrentHint = null;
       @Nullable private IndentGuideDescriptor myCurrentCaretGuide = null;
 
@@ -2289,6 +2289,8 @@
             position.x = drawSoftWrapAwareBackground(g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType,
                                                      defaultBackground, clip, softWrapsToSkip, caretRowPainted);
 
+            paintAfterLineEndBackgroundSegments(g, iterationState, position, defaultBackground, lineHeight);
+
             if (lIterator.getLineNumber() < lastLineIndex) {
               if (backColor != null && !backColor.equals(defaultBackground)) {
                 g.setColor(backColor);
@@ -2296,6 +2298,9 @@
               }
             }
             else {
+              if (iterationState.hasPastFileEndBackgroundSegments()) {
+                paintAfterLineEndBackgroundSegments(g, iterationState, position, defaultBackground, lineHeight);
+              }
               paintAfterFileEndBackground(iterationState,
                                           g,
                                           position, clip,
@@ -2380,6 +2385,24 @@
     }
   }
 
+  private void paintAfterLineEndBackgroundSegments(@NotNull Graphics g,
+                                                   @NotNull IterationState iterationState,
+                                                   @NotNull Point position,
+                                                   @NotNull Color defaultBackground,
+                                                   int lineHeight) {
+    while (iterationState.hasPastLineEndBackgroundSegment()) {
+      TextAttributes backgroundAttributes = iterationState.getPastLineEndBackgroundAttributes();
+      int width = EditorUtil.getSpaceWidth(backgroundAttributes.getFontType(), this) * iterationState.getPastLineEndBackgroundSegmentWidth();
+      Color color = getBackgroundColor(backgroundAttributes);
+      if (color != null && !color.equals(defaultBackground)) {
+        g.setColor(color);
+        g.fillRect(position.x, position.y, width, lineHeight);
+      }
+      position.x += width;
+      iterationState.advanceToNextPastLineEndBackgroundSegment();
+    }
+  }
+
   private void paintRectangularSelection(@NotNull Graphics g) {
     final SelectionModel model = getSelectionModel();
     if (!model.hasBlockSelection()) return;
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java
index 962230e..8349aac 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java
@@ -45,7 +45,6 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import javax.swing.*;
 import java.awt.*;
 import java.util.Arrays;
 import java.util.List;
@@ -201,7 +200,6 @@
   }
 
   private void runBatchFoldingOperation(final Runnable operation, final boolean dontCollapseCaret, final boolean moveCaret) {
-    assert SwingUtilities.isEventDispatchThread() : Thread.currentThread();
     assertIsDispatchThreadForEditor();
     boolean oldDontCollapseCaret = myDoNotCollapseCaret;
     myDoNotCollapseCaret |= dontCollapseCaret;
@@ -212,17 +210,20 @@
 
     myIsBatchFoldingProcessing = true;
     myFoldTree.myCachedLastIndex = -1;
-    operation.run();
-    myFoldTree.myCachedLastIndex = -1;
+    try {
+      operation.run();
+    } finally {
+      myFoldTree.myCachedLastIndex = -1;
 
-    if (!oldBatchFlag) {
-      if (myFoldRegionsProcessed) {
-        notifyBatchFoldingProcessingDone(moveCaret);
-        myFoldRegionsProcessed = false;
+      if (!oldBatchFlag) {
+        if (myFoldRegionsProcessed) {
+          notifyBatchFoldingProcessingDone(moveCaret);
+          myFoldRegionsProcessed = false;
+        }
+        myIsBatchFoldingProcessing = false;
       }
-      myIsBatchFoldingProcessing = false;
+      myDoNotCollapseCaret = oldDontCollapseCaret;
     }
-    myDoNotCollapseCaret = oldDontCollapseCaret;
   }
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java
index 3f3ed7e..4bd96fd 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java
@@ -17,13 +17,17 @@
 
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Caret;
 import com.intellij.openapi.editor.CaretModel;
 import com.intellij.openapi.editor.FoldRegion;
 import com.intellij.openapi.editor.RangeMarker;
 import com.intellij.openapi.editor.colors.EditorColors;
 import com.intellij.openapi.editor.ex.*;
 import com.intellij.openapi.editor.highlighter.HighlighterIterator;
-import com.intellij.openapi.editor.markup.*;
+import com.intellij.openapi.editor.markup.EffectType;
+import com.intellij.openapi.editor.markup.HighlighterLayer;
+import com.intellij.openapi.editor.markup.HighlighterTargetArea;
+import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.util.ArrayUtilRt;
 import com.intellij.util.containers.ContainerUtil;
@@ -89,7 +93,13 @@
 
   private final int[] mySelectionStarts;
   private final int[] mySelectionEnds;
+  private final int[] myVirtualSelectionStarts;
+  private final int[] myVirtualSelectionEnds;
   private int myCurrentSelectionIndex = 0;
+  private int myCurrentVirtualSelectionIndex = 0;
+  private boolean myCurrentLineHasVirtualSelection;
+  private int myCurrentPastLineEndBackgroundSegment; // 0 - before selection, 1 - in selection, 2 - after selection
+  private Color myCurrentBackgroundColor;
 
   private final List<RangeHighlighterEx> myCurrentHighlighters = new ArrayList<RangeHighlighterEx>();
 
@@ -123,8 +133,32 @@
     myHighlighterIterator = editor.getHighlighter().createIterator(start);
 
     boolean hasSelection = useCaretAndSelection && (editor.getCaretModel().supportsMultipleCarets() || editor.getSelectionModel().hasSelection() || editor.getSelectionModel().hasBlockSelection());
-    mySelectionStarts = hasSelection ? editor.getSelectionModel().getBlockSelectionStarts() : ArrayUtilRt.EMPTY_INT_ARRAY;
-    mySelectionEnds = hasSelection ? editor.getSelectionModel().getBlockSelectionEnds() : ArrayUtilRt.EMPTY_INT_ARRAY;
+    if (!hasSelection) {
+      mySelectionStarts = ArrayUtilRt.EMPTY_INT_ARRAY;
+      mySelectionEnds = ArrayUtilRt.EMPTY_INT_ARRAY;
+      myVirtualSelectionStarts = ArrayUtilRt.EMPTY_INT_ARRAY;
+      myVirtualSelectionEnds = ArrayUtilRt.EMPTY_INT_ARRAY;
+    }
+    else if (editor.getCaretModel().supportsMultipleCarets()) {
+      List<Caret> carets = editor.getCaretModel().getAllCarets();
+      mySelectionStarts = new int[carets.size()];
+      mySelectionEnds = new int[carets.size()];
+      myVirtualSelectionStarts = new int[carets.size()];
+      myVirtualSelectionEnds = new int[carets.size()];
+      for (int i = 0; i < carets.size(); i++) {
+        Caret caret = carets.get(i);
+        mySelectionStarts[i] = caret.getSelectionStart();
+        mySelectionEnds[i] = caret.getSelectionEnd();
+        myVirtualSelectionStarts[i] = caret.getSelectionStartPosition().column - editor.offsetToVisualPosition(mySelectionStarts[i]).column;
+        myVirtualSelectionEnds[i] = caret.getSelectionEndPosition().column - editor.offsetToVisualPosition(mySelectionEnds[i]).column;
+      }
+    }
+    else {
+      mySelectionStarts = editor.getSelectionModel().getBlockSelectionStarts();
+      mySelectionEnds = editor.getSelectionModel().getBlockSelectionEnds();
+      myVirtualSelectionStarts = new int[mySelectionStarts.length];
+      myVirtualSelectionEnds = new int[mySelectionEnds.length];
+    }
 
     myFoldingModel = editor.getFoldingModel();
     myFoldTextAttributes = myFoldingModel.getPlaceholderAttributes();
@@ -140,7 +174,7 @@
     myCaretRowStart = caretModel.getVisualLineStart();
     myCaretRowEnd = caretModel.getVisualLineEnd();
 
-    MarkupModelEx editorMarkup = (MarkupModelEx)editor.getMarkupModel();
+    MarkupModelEx editorMarkup = editor.getMarkupModel();
     myView = new HighlighterSweep(editorMarkup, start, myEnd);
 
     final MarkupModelEx docMarkup = (MarkupModelEx)DocumentMarkupModel.forDocument(editor.getDocument(), editor.getProject(), true);
@@ -181,31 +215,20 @@
 
     private void advance() {
       if (myNextHighlighter != null) {
-        if (myNextHighlighter.getAffectedAreaStartOffset() <= myStartOffset) {
-          myCurrentHighlighters.add(myNextHighlighter);
-          myNextHighlighter = null;
+        if (myNextHighlighter.getAffectedAreaStartOffset() > myStartOffset) {
+          return;
         }
-        
-        // There is a possible case that there are two highlighters mapped to offset of the first non-white space symbol
-        // on a line. The second one may have HighlighterTargetArea.LINES_IN_RANGE area, so, we should use it for indent
-        // background processing (that is the case for the active debugger line that starts with highlighted brace/bracket).
-        // So, we check if it's worth to use next highlighter here.
-        else if (myIterator.hasNext()) {
-          final RangeHighlighterEx lookAhead = myIterator.next();
-          if (lookAhead.getAffectedAreaStartOffset() <= myStartOffset) {
-            myCurrentHighlighters.add(lookAhead);
-          }
-          else {
-            myIterator.pushBack(lookAhead);
-          }
-        }
+
+        myCurrentHighlighters.add(myNextHighlighter);
+        myNextHighlighter = null;
       }
 
-      while (myNextHighlighter == null && myIterator.hasNext()) {
+      while (myIterator.hasNext()) {
         RangeHighlighterEx highlighter = myIterator.next();
         if (!skipHighlighter(highlighter)) {
           if (highlighter.getAffectedAreaStartOffset() > myStartOffset) {
             myNextHighlighter = highlighter;
+            break;
           }
           else {
             myCurrentHighlighters.add(highlighter);
@@ -237,6 +260,7 @@
     myStartOffset = myEndOffset;
     advanceSegmentHighlighters();
     advanceCurrentSelectionIndex();
+    advanceCurrentVirtualSelectionIndex();
 
     myCurrentFold = myFoldingModel.fetchOutermost(myStartOffset);
     if (myCurrentFold != null) {
@@ -298,6 +322,13 @@
     }
   }
 
+  private void advanceCurrentVirtualSelectionIndex() {
+    while (myCurrentVirtualSelectionIndex < mySelectionEnds.length
+           && (myStartOffset > mySelectionEnds[myCurrentVirtualSelectionIndex] || myVirtualSelectionEnds[myCurrentVirtualSelectionIndex] <= 0)) {
+      myCurrentVirtualSelectionIndex++;
+    }
+  }
+
   private int getSelectionEnd() {
     if (myCurrentSelectionIndex >= mySelectionStarts.length) {
       return myEnd;
@@ -402,12 +433,17 @@
     List<TextAttributes> cachedAttributes = myCachedAttributesList;
     cachedAttributes.clear();
 
+    int selectionAttributesIndex = -1; // a 'would-be' or real position of selection attributes in attributes list
+
     //noinspection ForLoopReplaceableByForEach
     for (int i = 0; i < size; i++) {
       RangeHighlighterEx highlighter = myCurrentHighlighters.get(i);
-      if (selection != null && highlighter.getLayer() < HighlighterLayer.SELECTION) {
-        cachedAttributes.add(selection);
-        selection = null;
+      if (highlighter.getLayer() < HighlighterLayer.SELECTION) {
+        selectionAttributesIndex = cachedAttributes.size();
+        if (selection != null) {
+          cachedAttributes.add(selection);
+          selection = null;
+        }
       }
 
       if (syntax != null && highlighter.getLayer() < HighlighterLayer.SYNTAX) {
@@ -436,6 +472,9 @@
       }
     }
 
+    if (selectionAttributesIndex < 0) {
+      selectionAttributesIndex = cachedAttributes.size();
+    }
     if (selection != null) cachedAttributes.add(selection);
     if (fold != null) cachedAttributes.add(fold);
     if (guard != null) cachedAttributes.add(guard);
@@ -448,6 +487,8 @@
     EffectType effectType = null;
     int fontType = 0;
 
+    boolean selectionBackgroundIsPotentiallyVisible = cachedAttributes.isEmpty();
+
     //noinspection ForLoopReplaceableByForEach
     for (int i = 0; i < cachedAttributes.size(); i++) {
       TextAttributes attrs = cachedAttributes.get(i);
@@ -457,6 +498,9 @@
       }
 
       if (back == null) {
+        if (isInSelection && i == selectionAttributesIndex || !isInSelection && i >= selectionAttributesIndex) {
+          selectionBackgroundIsPotentiallyVisible = true;
+        }
         back = ifDiffers(attrs.getBackgroundColor(), myDefaultBackground);
       }
 
@@ -475,6 +519,16 @@
     if (effectType == null) effectType = EffectType.BOXED;
 
     myMergedAttributes.setAttributes(fore, back, effect, null, effectType, fontType);
+
+    myCurrentBackgroundColor = back;
+    if (selectionBackgroundIsPotentiallyVisible && myCurrentVirtualSelectionIndex < mySelectionStarts.length && myStartOffset == mySelectionEnds[myCurrentVirtualSelectionIndex]) {
+      myCurrentLineHasVirtualSelection = true;
+      myCurrentPastLineEndBackgroundSegment = myVirtualSelectionStarts[myCurrentVirtualSelectionIndex] > 0 ? 0 : 1;
+    }
+    else {
+      myCurrentLineHasVirtualSelection = false;
+      myCurrentPastLineEndBackgroundSegment = 0;
+    }
   }
 
   @Nullable
@@ -504,6 +558,41 @@
     return myCurrentFold;
   }
 
+  public boolean hasPastLineEndBackgroundSegment() {
+    return myCurrentLineHasVirtualSelection && myCurrentPastLineEndBackgroundSegment < 2;
+  }
+
+  public int getPastLineEndBackgroundSegmentWidth() {
+    switch (myCurrentPastLineEndBackgroundSegment) {
+      case 0: return myVirtualSelectionStarts[myCurrentVirtualSelectionIndex];
+      case 1: return myVirtualSelectionEnds[myCurrentVirtualSelectionIndex] - myVirtualSelectionStarts[myCurrentVirtualSelectionIndex];
+      default: return 0;
+    }
+  }
+
+  @NotNull
+  public TextAttributes getPastLineEndBackgroundAttributes() {
+    myMergedAttributes.setBackgroundColor(myCurrentPastLineEndBackgroundSegment == 1 ? mySelectionAttributes.getBackgroundColor() : myCurrentBackgroundColor);
+    return myMergedAttributes;
+  }
+
+  public void advanceToNextPastLineEndBackgroundSegment() {
+    myCurrentPastLineEndBackgroundSegment++;
+  }
+
+  public boolean hasPastFileEndBackgroundSegments() {
+    myCurrentLineHasVirtualSelection = myVirtualSelectionEnds.length > 0
+                && myVirtualSelectionEnds[myVirtualSelectionEnds.length - 1] > 0
+                && myEndOffset == myEnd
+                && mySelectionEnds[mySelectionStarts.length - 1] == myEndOffset;
+    if (myCurrentLineHasVirtualSelection) {
+      myCurrentVirtualSelectionIndex = myVirtualSelectionStarts.length - 1;
+      myCurrentPastLineEndBackgroundSegment = myVirtualSelectionStarts[myCurrentVirtualSelectionIndex] > 0 ? 0 : 1;
+      myCurrentBackgroundColor = myEndOffset >= myCaretRowStart ? myCaretRowAttributes.getBackgroundColor() : myDefaultBackground;
+    }
+    return myCurrentLineHasVirtualSelection;
+  }
+
   @Nullable
   public Color getPastFileEndBackground() {
     boolean isInCaretRow = myEditor.getCaretModel().getLogicalPosition().line >= myDocument.getLineCount() - 1;
@@ -543,8 +632,8 @@
         return layerDiff;
       }
       // prefer more specific region
-      int o1Length = o1.getEndOffset() - o1.getStartOffset();
-      int o2Length = o2.getEndOffset() - o2.getStartOffset();
+      int o1Length = o1.getAffectedAreaEndOffset() - o1.getAffectedAreaStartOffset();
+      int o2Length = o2.getAffectedAreaEndOffset() - o2.getAffectedAreaStartOffset();
       return o1Length - o2Length;
     }
   }
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
index 46be8b8..7ee0e4d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
@@ -38,7 +38,6 @@
 import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.openapi.ide.CopyPasteManager;
 import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.containers.ContainerUtil;
@@ -47,7 +46,10 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.awt.datatransfer.StringSelection;
-import java.util.*;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
 
 public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentListener {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.SelectionModelImpl");
@@ -214,42 +216,40 @@
       int endLine = Math.max(Math.min(blockEnd.line, myEditor.getDocument().getLineCount() - 1), 0);
       int step = endLine < startLine ? -1 : 1;
       int count = 1 + Math.abs(endLine - startLine);
-      List<LogicalPosition> positions = new LinkedList<LogicalPosition>();
-      List<TextRange> selections = new LinkedList<TextRange>();
+      List<CaretState> caretStates = new LinkedList<CaretState>();
       boolean hasSelection = false;
       for (int line = startLine, i = 0; i < count; i++, line += step) {
         int startColumn = blockStart.column;
         int endColumn = blockEnd.column;
         int lineEndOffset = myEditor.getDocument().getLineEndOffset(line);
-        int lineWidth = myEditor.offsetToLogicalPosition(lineEndOffset).column;
-        if (startColumn > lineWidth && endColumn > lineWidth) {
+        LogicalPosition lineEndPosition = myEditor.offsetToLogicalPosition(lineEndOffset);
+        int lineWidth = lineEndPosition.column;
+        if (startColumn > lineWidth && endColumn > lineWidth && !myEditor.isColumnMode()) {
           LogicalPosition caretPos = new LogicalPosition(line, Math.min(startColumn, endColumn));
-          positions.add(caretPos);
-          selections.add(new TextRange(lineEndOffset, lineEndOffset));
+          caretStates.add(new CaretState(caretPos,
+                                         lineEndPosition,
+                                         lineEndPosition));
         }
         else {
-          LogicalPosition startPos = new LogicalPosition(line, Math.min(startColumn, lineWidth));
-          LogicalPosition endPos = new LogicalPosition(line, Math.min(endColumn, lineWidth));
+          LogicalPosition startPos = new LogicalPosition(line, myEditor.isColumnMode() ? startColumn : Math.min(startColumn, lineWidth));
+          LogicalPosition endPos = new LogicalPosition(line, myEditor.isColumnMode() ? endColumn : Math.min(endColumn, lineWidth));
           int startOffset = myEditor.logicalPositionToOffset(startPos);
           int endOffset = myEditor.logicalPositionToOffset(endPos);
-          positions.add(endPos);
-          selections.add(new TextRange(Math.min(startOffset, endOffset), Math.max(startOffset, endOffset)));
+          caretStates.add(new CaretState(endPos, startPos, endPos));
           hasSelection |= startOffset != endOffset;
         }
       }
       if (hasSelection && !myEditor.isColumnMode()) { // filtering out lines without selection
-        Iterator<LogicalPosition> positionIterator = positions.iterator();
-        Iterator<TextRange> selectionIterator = selections.iterator();
-        while(selectionIterator.hasNext()) {
-          TextRange selection = selectionIterator.next();
-          positionIterator.next();
-          if (selection.isEmpty()) {
-            selectionIterator.remove();
-            positionIterator.remove();
+        Iterator<CaretState> caretStateIterator = caretStates.iterator();
+        while(caretStateIterator.hasNext()) {
+          CaretState state = caretStateIterator.next();
+          //noinspection ConstantConditions
+          if (state.getSelectionStart().equals(state.getSelectionEnd())) {
+            caretStateIterator.remove();
           }
         }
       }
-      myEditor.getCaretModel().setCaretsAndSelections(positions, selections);
+      myEditor.getCaretModel().setCaretsAndSelections(caretStates);
     }
     else {
       removeSelection();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java
index 607e182..ef86c6f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java
@@ -18,7 +18,6 @@
 import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.event.CaretListener;
 import com.intellij.openapi.editor.markup.TextAttributes;
-import com.intellij.openapi.util.Segment;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -151,6 +150,11 @@
     return myCaret;
   }
 
+  @Override
+  public int getCaretCount() {
+    return 1;
+  }
+
   @NotNull
   @Override
   public List<Caret> getAllCarets() {
@@ -179,7 +183,7 @@
   }
 
   @Override
-  public void setCaretsAndSelections(@NotNull List<LogicalPosition> caretPositions, @NotNull List<? extends Segment> selections) {
+  public void setCaretsAndSelections(@NotNull List<CaretState> caretStates) {
     throw new UnsupportedOperationException("Multiple carets are not supported");
   }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
index 978c260..3216966 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
@@ -41,6 +41,7 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.LinkedHashSet;
 import java.util.List;
 
@@ -141,7 +142,7 @@
     }
     LOG.assertTrue(selectedEditor != null);
     final int selectedProviderIndex = ArrayUtilRt.find(editors, selectedEditor);
-    LOG.assertTrue(selectedProviderIndex != -1);
+    LOG.assertTrue(selectedProviderIndex != -1, "Can't find " + selectedEditor + " among " + Arrays.asList(editors));
 
     final HistoryEntry entry = getEntry(file);
     if(entry != null){
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
index 14af91d..5480381 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
@@ -37,6 +37,7 @@
 import com.intellij.openapi.editor.event.DocumentEvent;
 import com.intellij.openapi.editor.ex.DocumentEx;
 import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
+import com.intellij.openapi.editor.impl.EditorFactoryImpl;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.fileEditor.*;
 import com.intellij.openapi.fileEditor.impl.text.TextEditorImpl;
@@ -184,7 +185,7 @@
         document = (DocumentEx)getCachedDocument(file);
         if (document != null) return document; // Double checking
 
-        document = (DocumentEx)createDocument(text);
+        document = (DocumentEx)createDocument(text, file);
         document.setModificationStamp(file.getModificationStamp());
         final FileType fileType = file.getFileType();
         document.setReadOnly(!file.isWritable() || fileType.isBinary());
@@ -229,8 +230,9 @@
     return false;
   }
 
-  private static Document createDocument(final CharSequence text) {
-    return EditorFactory.getInstance().createDocument(text);
+  private static Document createDocument(final CharSequence text, VirtualFile file) {
+    boolean acceptSlashR = file instanceof LightVirtualFile && StringUtil.indexOf(text, '\r') >= 0;
+    return ((EditorFactoryImpl)EditorFactory.getInstance()).createDocument(text, acceptSlashR, false);
   }
 
   @Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java
index 6e80c6d..752ab12 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java
@@ -119,7 +119,7 @@
     };
     eventMulticaster.addDocumentListener(documentListener, myProject);
 
-    CaretListener caretListener = new CaretListener() {
+    CaretListener caretListener = new CaretAdapter() {
       @Override
       public void caretPositionChanged(CaretEvent e) {
         onCaretPositionChanged(e);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java
index 1ffd027..d7b881a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java
@@ -50,6 +50,7 @@
 import com.intellij.openapi.wm.ex.StatusBarEx;
 import com.intellij.ui.components.JBLoadingPanel;
 import com.intellij.util.EditorPopupHandler;
+import com.intellij.util.FileContentUtilCore;
 import com.intellij.util.messages.MessageBusConnection;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -348,7 +349,9 @@
         // File can be invalidated after file changes name (extension also
         // can changes). The editor should be removed if it's invalid.
         updateValidProperty();
-        if (Comparing.equal(e.getFile(), myFile) && !Comparing.equal(e.getOldValue(), e.getNewValue())) {
+        if (Comparing.equal(e.getFile(), myFile) &&
+            (FileContentUtilCore.FORCE_RELOAD_REQUESTOR.equals(e.getRequestor()) ||
+             !Comparing.equal(e.getOldValue(), e.getNewValue()))) {
           updateHighlighters();
         }
       }
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
index 4514ee8..47c0088 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
@@ -57,8 +57,10 @@
   @NonNls private static final String TYPE_ID                         = "text-editor";
   @NonNls private static final String LINE_ATTR                       = "line";
   @NonNls private static final String COLUMN_ATTR                     = "column";
-  @NonNls private static final String SELECTION_START_ATTR            = "selection-start";
-  @NonNls private static final String SELECTION_END_ATTR              = "selection-end";
+  @NonNls private static final String SELECTION_START_LINE_ATTR       = "selection-start-line";
+  @NonNls private static final String SELECTION_START_COLUMN_ATTR     = "selection-start-column";
+  @NonNls private static final String SELECTION_END_LINE_ATTR         = "selection-end-line";
+  @NonNls private static final String SELECTION_END_COLUMN_ATTR       = "selection-end-column";
   @NonNls private static final String VERTICAL_SCROLL_PROPORTION_ATTR = "vertical-scroll-proportion";
   @NonNls private static final String VERTICAL_OFFSET_ATTR            = "vertical-offset";
   @NonNls private static final String MAX_VERTICAL_OFFSET_ATTR        = "max-vertical-offset";
@@ -100,10 +102,10 @@
 
     try {
       List<Element> caretElements = element.getChildren(CARET_ELEMENT);
-      if (caretElements.isEmpty()) { // legacy format
+      if (caretElements.isEmpty()) {
         state.CARETS = new TextEditorState.CaretState[] {readCaretInfo(element)};
       }
-      else { // new format
+      else {
         state.CARETS = new TextEditorState.CaretState[caretElements.size()];
         for (int i = 0; i < caretElements.size(); i++) {
           state.CARETS[i] = readCaretInfo(caretElements.get(i));
@@ -129,8 +131,10 @@
     TextEditorState.CaretState caretState = new TextEditorState.CaretState();
     caretState.LINE = parseWithDefault(element, LINE_ATTR);
     caretState.COLUMN = parseWithDefault(element, COLUMN_ATTR);
-    caretState.SELECTION_START = parseWithDefault(element, SELECTION_START_ATTR);
-    caretState.SELECTION_END = parseWithDefault(element, SELECTION_END_ATTR);
+    caretState.SELECTION_START_LINE = parseWithDefault(element, SELECTION_START_LINE_ATTR);
+    caretState.SELECTION_START_COLUMN = parseWithDefault(element, SELECTION_START_COLUMN_ATTR);
+    caretState.SELECTION_END_LINE = parseWithDefault(element, SELECTION_END_LINE_ATTR);
+    caretState.SELECTION_END_COLUMN = parseWithDefault(element, SELECTION_END_COLUMN_ATTR);
     return caretState;
   }
 
@@ -151,8 +155,10 @@
         Element e = new Element(CARET_ELEMENT);
         e.setAttribute(LINE_ATTR, Integer.toString(caretState.LINE));
         e.setAttribute(COLUMN_ATTR, Integer.toString(caretState.COLUMN));
-        e.setAttribute(SELECTION_START_ATTR, Integer.toString(caretState.SELECTION_START));
-        e.setAttribute(SELECTION_END_ATTR, Integer.toString(caretState.SELECTION_END));
+        e.setAttribute(SELECTION_START_LINE_ATTR, Integer.toString(caretState.SELECTION_START_LINE));
+        e.setAttribute(SELECTION_START_COLUMN_ATTR, Integer.toString(caretState.SELECTION_START_COLUMN));
+        e.setAttribute(SELECTION_END_LINE_ATTR, Integer.toString(caretState.SELECTION_END_LINE));
+        e.setAttribute(SELECTION_END_COLUMN_ATTR, Integer.toString(caretState.SELECTION_END_COLUMN));
         element.addContent(e);
       }
     }
@@ -227,8 +233,12 @@
       state.CARETS[i] = new TextEditorState.CaretState();
       state.CARETS[i].LINE = caret.getLogicalPosition().line;
       state.CARETS[i].COLUMN = caret.getLogicalPosition().column;
-      state.CARETS[i].SELECTION_START = caret.getSelectionStart();
-      state.CARETS[i++].SELECTION_END = caret.getSelectionEnd();
+      LogicalPosition selectionStartPosition = editor.visualToLogicalPosition(caret.getSelectionStartPosition());
+      LogicalPosition selectionEndPosition = editor.visualToLogicalPosition(caret.getSelectionEndPosition());
+      state.CARETS[i].SELECTION_START_LINE = selectionStartPosition.line;
+      state.CARETS[i].SELECTION_START_COLUMN = selectionStartPosition.column;
+      state.CARETS[i].SELECTION_END_LINE = selectionEndPosition.line;
+      state.CARETS[i++].SELECTION_END_COLUMN = selectionEndPosition.column;
     }
 
     // Saving scrolling proportion on UNDO may cause undesirable results of undo action fails to perform since
@@ -246,13 +256,13 @@
   protected void setStateImpl(final Project project, final Editor editor, final TextEditorState state){
     if (editor.getCaretModel().supportsMultipleCarets()) {
       CaretModel caretModel = editor.getCaretModel();
-      ArrayList<LogicalPosition> positions = new ArrayList<LogicalPosition>();
-      ArrayList<Segment> selections = new ArrayList<Segment>();
+      List<CaretState> states = new ArrayList<CaretState>(state.CARETS.length);
       for (TextEditorState.CaretState caretState : state.CARETS) {
-        positions.add(new LogicalPosition(caretState.LINE, caretState.COLUMN));
-        selections.add(new TextRange(caretState.SELECTION_START, caretState.SELECTION_END));
+        states.add(new CaretState(new LogicalPosition(caretState.LINE, caretState.COLUMN),
+                                  new LogicalPosition(caretState.SELECTION_START_LINE, caretState.SELECTION_START_COLUMN),
+                                  new LogicalPosition(caretState.SELECTION_END_LINE, caretState.SELECTION_END_COLUMN)));
       }
-      caretModel.setCaretsAndSelections(positions, selections);
+      caretModel.setCaretsAndSelections(states);
     } else {
       LogicalPosition pos = new LogicalPosition(state.CARETS[0].LINE, state.CARETS[0].COLUMN);
       editor.getCaretModel().moveToLogicalPosition(pos);
@@ -275,15 +285,14 @@
       }
     }
 
-    final Document document = editor.getDocument();
-
     if (!editor.getCaretModel().supportsMultipleCarets()) {
-      if (state.CARETS[0].SELECTION_START == state.CARETS[0].SELECTION_END) {
+      if (state.CARETS[0].SELECTION_START_LINE == state.CARETS[0].SELECTION_END_LINE
+          && state.CARETS[0].SELECTION_START_COLUMN == state.CARETS[0].SELECTION_END_COLUMN) {
         editor.getSelectionModel().removeSelection();
       }
       else {
-        int startOffset = Math.min(state.CARETS[0].SELECTION_START, document.getTextLength());
-        int endOffset = Math.min(state.CARETS[0].SELECTION_END, document.getTextLength());
+        int startOffset = editor.logicalPositionToOffset(new LogicalPosition(state.CARETS[0].SELECTION_START_LINE, state.CARETS[0].SELECTION_START_COLUMN));
+        int endOffset = editor.logicalPositionToOffset(new LogicalPosition(state.CARETS[0].SELECTION_END_LINE, state.CARETS[0].SELECTION_END_COLUMN));
         editor.getSelectionModel().setSelection(startOffset, endOffset);
       }
     }
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorState.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorState.java
index 3319d51..d4aca48 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorState.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorState.java
@@ -122,8 +122,10 @@
   public static class CaretState {
     public int   LINE;
     public int   COLUMN;
-    public int   SELECTION_START;
-    public int   SELECTION_END;
+    public int   SELECTION_START_LINE;
+    public int   SELECTION_START_COLUMN;
+    public int   SELECTION_END_LINE;
+    public int   SELECTION_END_COLUMN;
 
     public boolean equals(Object o) {
       if (!(o instanceof CaretState)) {
@@ -134,8 +136,10 @@
 
       if (COLUMN != caretState.COLUMN) return false;
       if (LINE != caretState.LINE) return false;
-      if (SELECTION_START != caretState.SELECTION_START) return false;
-      if (SELECTION_END != caretState.SELECTION_END) return false;
+      if (SELECTION_START_LINE != caretState.SELECTION_START_LINE) return false;
+      if (SELECTION_START_COLUMN != caretState.SELECTION_START_COLUMN) return false;
+      if (SELECTION_END_LINE != caretState.SELECTION_END_LINE) return false;
+      if (SELECTION_END_COLUMN != caretState.SELECTION_END_COLUMN) return false;
 
       return true;
     }
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java
index 77e55ea..817cdaa 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java
@@ -651,8 +651,8 @@
       if (!(component instanceof JComponent)) {
         continue;
       }
-      ArrayList listOfActions = (ArrayList)((JComponent)component).getClientProperty(AnAction.ourClientProperty);
-      if (listOfActions == null) {
+      List<AnAction> listOfActions = ActionUtil.getActions((JComponent)component);
+      if (listOfActions.isEmpty()) {
         continue;
       }
       for (Object listOfAction : listOfActions) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
index b809539..94f72f6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
@@ -19,6 +19,7 @@
 import com.intellij.ide.DataManager;
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
+import com.intellij.openapi.actionSystem.ex.ActionUtil;
 import com.intellij.openapi.actionSystem.impl.PresentationFactory;
 import com.intellij.openapi.keymap.Keymap;
 import com.intellij.openapi.keymap.KeymapManager;
@@ -78,21 +79,16 @@
 
     // here we try to find "local" shortcuts
     if (component instanceof JComponent) {
-      @SuppressWarnings("unchecked")
-      final ArrayList<AnAction> listOfActions = (ArrayList<AnAction>)((JComponent)component).getClientProperty(AnAction.ourClientProperty);
-      if (listOfActions != null) {
-        for (AnAction action : listOfActions) {
-          final Shortcut[] shortcuts = action.getShortcutSet().getShortcuts();
-          for (Shortcut shortcut : shortcuts) {
-            if (mouseShortcut.equals(shortcut) && !myActions.contains(action)) {
-              myActions.add(action);
-            }
+      for (AnAction action : ActionUtil.getActions((JComponent)component)) {
+        for (Shortcut shortcut : action.getShortcutSet().getShortcuts()) {
+          if (mouseShortcut.equals(shortcut) && !myActions.contains(action)) {
+            myActions.add(action);
           }
         }
-        // once we've found a proper local shortcut(s), we exit
-        if (! myActions.isEmpty()) {
-          return;
-        }
+      }
+      // once we've found a proper local shortcut(s), we exit
+      if (!myActions.isEmpty()) {
+        return;
       }
     }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java
index 5751e4a..ada7802 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java
@@ -15,8 +15,6 @@
  */
 package com.intellij.openapi.project.impl;
 
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.ProjectManager;
 import org.jetbrains.annotations.NotNull;
 
@@ -34,13 +32,4 @@
   public boolean isDefault() {
     return true;
   }
-
-  @Override
-  public synchronized void dispose() {
-    if (!ApplicationManager.getApplication().isDisposeInProgress() && !ApplicationManager.getApplication().isUnitTestMode()) {
-      Logger.getInstance(DefaultProject.class).error(new Exception("Too young to die"));
-    }
-
-    super.dispose();
-  }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
index 35586cf..90cbffe 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
@@ -263,7 +263,7 @@
 
   private void initProject(@NotNull ProjectImpl project, @Nullable ProjectImpl template) throws IOException {
     final ProgressIndicator indicator = myProgressManager.getProgressIndicator();
-    if (indicator != null) {
+    if (indicator != null && !project.isDefault()) {
       indicator.setText(ProjectBundle.message("loading.components.for", project.getName()));
       indicator.setIndeterminate(true);
     }
@@ -299,6 +299,10 @@
   }
 
   private static void scheduleDispose(final ProjectImpl project) {
+    if (project.isDefault()) {
+      return;
+    }
+
     ApplicationManager.getApplication().invokeLater(new Runnable() {
       @Override
       public void run() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java
index aa7b6b3..d54bfcc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java
@@ -251,6 +251,7 @@
               if (project.isDisposed()) return;
               if (extensions == null) {
                 loadSupportedExtensions(myAllPlugins);
+                if (project.isDisposed()) return;
                 EditorNotifications.getInstance(project).updateAllNotifications();
               }
               final Map<String, Plugin> ids = new HashMap<String, Plugin>();
@@ -280,7 +281,9 @@
 
               for (IdeaPluginDescriptor loadedPlugin : myAllPlugins) {
                 final PluginId pluginId = loadedPlugin.getPluginId();
-                if (ids.containsKey(pluginId.getIdString()) && !disabledPlugins.contains(pluginId.getIdString())) {
+                if (ids.containsKey(pluginId.getIdString()) && 
+                    !disabledPlugins.contains(pluginId.getIdString()) && 
+                    !PluginManagerCore.isBrokenPlugin(loadedPlugin)) {
                   myPlugins.add(PluginDownloader.createDownloader(loadedPlugin));
                 }
               }
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/VirtualFileImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/VirtualFileImpl.java
index 3c1922e..be96d70 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/VirtualFileImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/VirtualFileImpl.java
@@ -1,6 +1,5 @@
-
 /*
- * Copyright 2000-2011 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.
@@ -45,6 +44,7 @@
     return myFileSystem;
   }
 
+  @NotNull
   @Override
   public String getPath() {
     if (myParent == null) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java
index 110d710..873ac02 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java
@@ -102,6 +102,7 @@
     return myFileSystem;
   }
 
+  @NotNull
   @Override
   public String getPath() {
     return myPath;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
index 7f0b5e8..e12d756 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.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.
@@ -260,14 +260,14 @@
             private final byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
 
             @Override
-            public void save(DataOutput out, CacheLibraryInfo value) throws IOException {
+            public void save(@NotNull DataOutput out, CacheLibraryInfo value) throws IOException {
               IOUtil.writeUTFFast(myBuffer, out, value.mySnapshotPath);
               out.writeLong(value.myModificationTime);
               out.writeLong(value.myFileLength);
             }
 
             @Override
-            public CacheLibraryInfo read(DataInput in) throws IOException {
+            public CacheLibraryInfo read(@NotNull DataInput in) throws IOException {
               return new CacheLibraryInfo(IOUtil.readUTFFast(myBuffer, in), in.readLong(), in.readLong());
             }
           }
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FakeVirtualFile.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FakeVirtualFile.java
index 2486124..5dc589f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FakeVirtualFile.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FakeVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -38,6 +38,7 @@
     return myParent;
   }
 
+  @NotNull
   @Override
   public String getPath() {
     final String basePath = myParent.getPath();
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java
index ab9655a..3f2c4ab 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.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.
@@ -42,12 +42,12 @@
 
   public static int storeName(@NotNull String name) {
     final int idx = FSRecords.getNameId(name);
-    cacheData(name, idx);
+    cacheData(name, idx, calcStripeIdFromNameId(idx));
     return idx;
   }
 
   @NotNull
-  private static IntObjectLinkedMap.MapEntry<Object> cacheData(String name, int id) {
+  private static IntObjectLinkedMap.MapEntry<Object> cacheData(String name, int id, int stripe) {
     if (name == null) {
       ourNames.markCorrupted();
       throw new RuntimeException("VFS name enumerator corrupted");
@@ -55,7 +55,6 @@
 
     Object rawName = convertToBytesIfAsciiString(name);
     IntObjectLinkedMap.MapEntry<Object> entry = new IntObjectLinkedMap.MapEntry<Object>(id, rawName);
-    final int stripe = calcStripeIdFromNameId(id);
     synchronized (ourNameCache[stripe]) {
       return ourNameCache[stripe].cacheEntry(entry);
     }
@@ -99,7 +98,7 @@
       }
     }
 
-    return cacheData(FSRecords.getNameByNameId(id), id);
+    return cacheData(FSRecords.getNameByNameId(id), id, stripe);
   }
 
   @NotNull
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java
index 33c024f..94f7369 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
 import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
 import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
+import com.intellij.util.LineSeparator;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -124,4 +125,19 @@
   public OutputStream getOutputStream(final Object requestor, final long modStamp, final long timeStamp) throws IOException {
     return VfsUtilCore.outputStreamAddingBOM(ourPersistence.getOutputStream(this, requestor, modStamp, timeStamp), this);
   }
+
+  @Override
+  public String getDetectedLineSeparator() {
+    if (getFlagInt(SYSTEM_LINE_SEPARATOR_DETECTED)) {
+      return LineSeparator.getSystemLineSeparator().getSeparatorString();
+    }
+    return super.getDetectedLineSeparator();
+  }
+
+  @Override
+  public void setDetectedLineSeparator(String separator) {
+    boolean hasSystemSeparator = LineSeparator.getSystemLineSeparator().getSeparatorString().equals(separator);
+    setFlagInt(SYSTEM_LINE_SEPARATOR_DETECTED, hasSystemSeparator);
+    super.setDetectedLineSeparator(hasSystemSeparator ? null : separator);
+  }
 }
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileSystemEntry.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileSystemEntry.java
index 2d5b519..e0772bc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileSystemEntry.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileSystemEntry.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.
@@ -52,14 +52,15 @@
 
   private static final Key<String> SYMLINK_TARGET = Key.create("local.vfs.symlink.target");
 
+  private static final int IS_WRITABLE_FLAG = 0x01000000;
+  private static final int IS_HIDDEN_FLAG =   0x02000000;
+  private static final int INDEXED_FLAG =     0x04000000;
+          static final int CHILDREN_CACHED =  0x08000000; // makes sense for directory only
   private static final int DIRTY_FLAG =       0x10000000;
   private static final int IS_SYMLINK_FLAG =  0x20000000;
   private static final int HAS_SYMLINK_FLAG = 0x40000000;
   private static final int IS_SPECIAL_FLAG =  0x80000000;
-  private static final int IS_WRITABLE_FLAG = 0x01000000;
-  private static final int IS_HIDDEN_FLAG =   0x02000000;
-  private static final int INDEXED_FLAG =     0x04000000;
-          static final int CHILDREN_CACHED =  0x08000000;
+          static final int SYSTEM_LINE_SEPARATOR_DETECTED = CHILDREN_CACHED; // makes sense only for non-directory file
 
   private static final int ALL_FLAGS_MASK =
     DIRTY_FLAG | IS_SYMLINK_FLAG | HAS_SYMLINK_FLAG | IS_SPECIAL_FLAG | IS_WRITABLE_FLAG | IS_HIDDEN_FLAG | INDEXED_FLAG | CHILDREN_CACHED;
@@ -68,6 +69,10 @@
   private volatile VirtualDirectoryImpl myParent;
   private volatile int myFlags;
   private volatile int myId;
+  
+  static {
+    assert (~ALL_FLAGS_MASK) == LocalTimeCounter.TIME_MASK;
+  }
 
   public VirtualFileSystemEntry(int nameId, VirtualDirectoryImpl parent, int id, @PersistentFS.Attributes int attributes) {
     myParent = parent;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java
index c1c7cd6..de9a6d5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -543,12 +543,12 @@
 
     private static class ContentHashesDescriptor implements KeyDescriptor<byte[]>, DifferentSerializableBytesImplyNonEqualityPolicy {
       @Override
-      public void save(DataOutput out, byte[] value) throws IOException {
+      public void save(@NotNull DataOutput out, byte[] value) throws IOException {
         out.write(value);
       }
 
       @Override
-      public byte[] read(DataInput in) throws IOException {
+      public byte[] read(@NotNull DataInput in) throws IOException {
         byte[] b = new byte[SIGNATURE_LENGTH];
         in.readFully(b);
         return b;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
index 09de7d3..7719e78 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
@@ -52,7 +52,12 @@
   private Cursor myLastOriginalCursor;
   private MouseEvent myPrevPressEvent;
 
-  private JPanel myFocusProxy = new JPanel();
+  private JPanel myFocusProxy = new JPanel(){
+    @Override
+    public String toString() {
+      return "FocusProxy";
+    }
+  };
 
   public IdeGlassPaneImpl(JRootPane rootPane) {
     myRootPane = rootPane;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java
index 9be7a92..5103ce7 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -17,10 +17,7 @@
 
 import com.intellij.ide.util.GotoLineNumberDialog;
 import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.EditorFactory;
-import com.intellij.openapi.editor.LogicalPosition;
-import com.intellij.openapi.editor.SelectionModel;
+import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.event.*;
 import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
 import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
@@ -33,6 +30,7 @@
 
 import java.awt.*;
 import java.awt.event.MouseEvent;
+import java.util.List;
 
 public class PositionPanel extends EditorBasedWidget implements StatusBarWidget.Multiframe, StatusBarWidget.TextPresentation, CaretListener, SelectionListener {
   private String myText;
@@ -124,6 +122,16 @@
     updatePosition(e.getEditor());
   }
 
+  @Override
+  public void caretAdded(CaretEvent e) {
+    updatePosition(e.getEditor());
+  }
+
+  @Override
+  public void caretRemoved(CaretEvent e) {
+    updatePosition(e.getEditor());
+  }
+
   private void updatePosition(final Editor editor) {
     if (editor == null) {
       myText = "";
@@ -157,12 +165,23 @@
         );
       }
       else {
-        LogicalPosition caret = editor.getCaretModel().getLogicalPosition();
+        List<Caret> carets = editor.getCaretModel().getAllCarets();
+        if (carets.size() > 1) {
+          message.append(carets.size()).append(" carets (");
+          appendLogicalPosition(carets.get(0).getLogicalPosition(), message);
+          message.append('-');
+          appendLogicalPosition(carets.get(carets.size() - 1).getLogicalPosition(), message);
+          message.append(')');
+        }
+        else {
+          Caret caret = carets.get(0);
+          LogicalPosition caretPosition = caret.getLogicalPosition();
 
-        appendLogicalPosition(caret, message);
-        if (selectionModel.hasSelection()) {
-          int len = Math.abs(selectionModel.getSelectionStart() - selectionModel.getSelectionEnd());
-          if (len != 0) message.append("/").append(len);
+          appendLogicalPosition(caretPosition, message);
+          if (caret.hasSelection()) {
+            int len = Math.abs(caret.getSelectionStart() - caret.getSelectionEnd());
+            if (len != 0) message.append("/").append(len);
+          }
         }
       }
 
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java
index d4477a3..8fd1559 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToolWindowsWidget.java
@@ -72,8 +72,13 @@
       @Override
       public boolean dispatch(AWTEvent e) {
         if (e instanceof MouseEvent) {
+          MouseEvent mouseEvent = (MouseEvent)e;
+          if (mouseEvent.getComponent() == null || !SwingUtilities.isDescendingFrom(mouseEvent.getComponent(), SwingUtilities.getWindowAncestor(ToolWindowsWidget.this))) {
+            return false;
+          }
+
           if (e.getID() == MouseEvent.MOUSE_MOVED && isShowing()) {
-            Point p = ((MouseEvent)e).getLocationOnScreen();
+            Point p = mouseEvent.getLocationOnScreen();
             Point screen = ToolWindowsWidget.this.getLocationOnScreen();
             if (new Rectangle(screen.x - 4, screen.y - 2, getWidth() + 4, getHeight() + 4).contains(p)) {
               mouseEntered();
@@ -85,7 +90,7 @@
             }
           } else if (e.getID() == MouseEvent.MOUSE_EXITED) {
             //mouse exits WND
-            mouseExited(((MouseEvent)e).getLocationOnScreen());
+            mouseExited(mouseEvent.getLocationOnScreen());
           }
         }
         return false;
diff --git a/platform/platform-impl/src/com/intellij/remote/MutableRemoteCredentials.java b/platform/platform-impl/src/com/intellij/remote/MutableRemoteCredentials.java
new file mode 100644
index 0000000..5f8d33b
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/MutableRemoteCredentials.java
@@ -0,0 +1,45 @@
+/*
+ * 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.intellij.remote;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author traff
+ */
+public interface MutableRemoteCredentials extends RemoteCredentials {
+  void setHost(String host);
+
+  void setPort(int port);
+
+  void setUserName(String userName);
+
+  void setPassword(@Nullable String password);
+
+  void setStorePassword(boolean storePassword);
+
+  void setStorePassphrase(boolean storePassphrase);
+
+  void setAnonymous(boolean anonymous);
+
+  void setPrivateKeyFile(String privateKeyFile);
+
+  void setKnownHostsFile(String knownHostsFile);
+
+  void setPassphrase(@Nullable String passphrase);
+
+  void setUseKeyPair(boolean useKeyPair);
+}
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteCancelledException.java b/platform/platform-impl/src/com/intellij/remote/RemoteCancelledException.java
new file mode 100644
index 0000000..da38b1a
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteCancelledException.java
@@ -0,0 +1,10 @@
+package com.intellij.remote;
+
+/**
+ * @author traff
+ */
+public class RemoteCancelledException extends RemoteSdkException {
+  public RemoteCancelledException(String s) {
+    super(s);
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
new file mode 100644
index 0000000..a90f4a4
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.remote;
+
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataHolderBase;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author traff
+ */
+public class RemoteConnectionCredentialsWrapper {
+  public static final String VAGRANT_PREFIX = "vagrant://";
+  public static final String SFTP_DEPLOYMENT_PREFIX = "sftp://";
+
+  public final Key<VagrantBasedCredentialsHolder> VAGRANT_BASED_CREDENTIALS = Key.create("VAGRANT_BASED_CREDENTIALS");
+  public final Key<WebDeploymentCredentialsHolder> WEB_DEPLOYMENT_BASED_CREDENTIALS = Key.create("WEB_DEPLOYMENT_BASED_CREDENTIALS");
+
+  public final Key<RemoteCredentialsHolder> PLAIN_SSH_CREDENTIALS = Key.create("PLAIN_SSH_CREDENTIALS");
+
+  private UserDataHolderBase myCredentialsTypeHolder = new UserDataHolderBase();
+
+  public void setVagrantConnectionType(VagrantBasedCredentialsHolder vagrantBasedCredentials) {
+    myCredentialsTypeHolder.putUserData(VAGRANT_BASED_CREDENTIALS, vagrantBasedCredentials);
+  }
+
+
+  private VagrantBasedCredentialsHolder getVagrantCredentials() {
+    return myCredentialsTypeHolder.getUserData(VAGRANT_BASED_CREDENTIALS);
+  }
+
+  public void setPlainSshCredentials(RemoteCredentialsHolder credentials) {
+    myCredentialsTypeHolder.putUserData(PLAIN_SSH_CREDENTIALS, credentials);
+  }
+
+  private RemoteCredentialsHolder getPlainSshCredentials() {
+    return myCredentialsTypeHolder.getUserData(PLAIN_SSH_CREDENTIALS);
+  }
+
+
+  public void setWebDeploymentCredentials(WebDeploymentCredentialsHolder webDeploymentCredentials) {
+    myCredentialsTypeHolder.putUserData(WEB_DEPLOYMENT_BASED_CREDENTIALS, webDeploymentCredentials);
+  }
+
+  private WebDeploymentCredentialsHolder getWebDeploymentCredentials() {
+    return myCredentialsTypeHolder.getUserData(WEB_DEPLOYMENT_BASED_CREDENTIALS);
+  }
+
+  private boolean isVagrantConnection() {
+    return getVagrantCredentials() != null;
+  }
+
+  private boolean isPlainSshConnection() {
+    return getPlainSshCredentials() != null;
+  }
+
+  private boolean isWebDeploymentConnection() {
+    return getWebDeploymentCredentials() != null;
+  }
+
+
+  public Object getConnectionKey() {
+    if (isVagrantConnection()) {
+      return getVagrantCredentials();
+    }
+    else if (isPlainSshConnection()) {
+      return getPlainSshCredentials();
+    }
+    else if (isWebDeploymentConnection()) {
+      return getWebDeploymentCredentials();
+    }
+    else {
+      throw unknownConnectionType();
+    }
+  }
+
+  public void save(final Element rootElement) {
+    switchType(new RemoteSdkConnectionAcceptor() {
+      @Override
+      public void ssh(RemoteCredentialsHolder cred) {
+        cred.save(rootElement);
+      }
+
+      @Override
+      public void vagrant(VagrantBasedCredentialsHolder cred) {
+        cred.save(rootElement);
+      }
+
+      @Override
+      public void deployment(WebDeploymentCredentialsHolder cred) {
+        cred.save(rootElement);
+      }
+    });
+  }
+
+  public static IllegalStateException unknownConnectionType() {
+    return new IllegalStateException("Unknown connection type"); //TODO
+  }
+
+  public void copyTo(RemoteConnectionCredentialsWrapper copy) {
+    copy.myCredentialsTypeHolder = new UserDataHolderBase();
+    copy.setPlainSshCredentials(getPlainSshCredentials());
+    copy.setVagrantConnectionType(getVagrantCredentials());
+    copy.setWebDeploymentCredentials(getWebDeploymentCredentials());
+  }
+
+  public String getId() {
+    if (isVagrantConnection()) {
+      @NotNull VagrantBasedCredentialsHolder cred = getVagrantCredentials();
+
+      return VAGRANT_PREFIX + cred.getVagrantFolder();
+    }
+    else if (isPlainSshConnection()) {
+      RemoteCredentials cred = getPlainSshCredentials();
+
+      return constructSshCredentialsFullPath(cred);
+    }
+    else if (isWebDeploymentConnection()) {
+      WebDeploymentCredentialsHolder cred = getWebDeploymentCredentials();
+      return constructSftpCredentialsFullPath(cred.getSshCredentials());
+    }
+    else {
+      throw unknownConnectionType();
+    }
+  }
+
+  private static String constructSftpCredentialsFullPath(RemoteCredentials cred) {
+    return SFTP_DEPLOYMENT_PREFIX + cred.getUserName() + "@" + cred.getHost() + ":" + cred.getPort();
+  }
+
+
+  public static String constructSshCredentialsFullPath(RemoteCredentials cred) {
+    return RemoteSdkCredentialsHolder.SSH_PREFIX + cred.getUserName() + "@" + cred.getHost() + ":" + cred.getPort();
+  }
+
+  public void switchType(RemoteSdkConnectionAcceptor acceptor) {
+    if (isVagrantConnection()) {
+      acceptor.vagrant(getVagrantCredentials());
+    }
+    else if (isPlainSshConnection()) {
+      acceptor.ssh(getPlainSshCredentials());
+    }
+    else if (isWebDeploymentConnection()) {
+      acceptor.deployment(getWebDeploymentCredentials());
+    }
+    else {
+      throw unknownConnectionType();
+    }
+  }
+
+  public interface RemoteSdkConnectionAcceptor {
+    void ssh(RemoteCredentialsHolder cred);
+    void vagrant(VagrantBasedCredentialsHolder cred);
+    void deployment(WebDeploymentCredentialsHolder cred);
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteCredentials.java b/platform/platform-impl/src/com/intellij/remote/RemoteCredentials.java
new file mode 100644
index 0000000..74f1be78
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteCredentials.java
@@ -0,0 +1,47 @@
+/*
+ * 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.intellij.remote;
+
+import com.intellij.util.xmlb.annotations.Transient;
+
+/**
+ * @author traff
+ */
+public interface RemoteCredentials {
+  String getHost();
+
+  int getPort();
+
+  @Transient
+  String getUserName();
+
+  String getPassword();
+
+  @Transient
+  String getPassphrase();
+
+  boolean isUseKeyPair();
+
+  boolean isAnonymous();
+
+  String getPrivateKeyFile();
+
+  boolean isStorePassword();
+
+  boolean isStorePassphrase();
+
+  String getKnownHostsFile();
+}
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteCredentialsHolder.java b/platform/platform-impl/src/com/intellij/remote/RemoteCredentialsHolder.java
new file mode 100644
index 0000000..5f5efb7
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteCredentialsHolder.java
@@ -0,0 +1,260 @@
+/*
+ * 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.intellij.remote;
+
+import com.intellij.openapi.util.PasswordUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.remote.MutableRemoteCredentials;
+import com.intellij.remote.RemoteCredentials;
+import com.intellij.remote.RemoteSdkCredentials;
+import com.intellij.util.xmlb.annotations.Transient;
+import org.jdom.Element;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author michael.golubev
+ */
+public class RemoteCredentialsHolder implements MutableRemoteCredentials {
+
+  public static final String HOST = "HOST";
+  public static final String PORT = "PORT";
+  public static final String ANONYMOUS = "ANONYMOUS";
+  public static final String USERNAME = "USERNAME";
+  public static final String PASSWORD = "PASSWORD";
+  public static final String USE_KEY_PAIR = "USE_KEY_PAIR";
+  public static final String PRIVATE_KEY_FILE = "PRIVATE_KEY_FILE";
+  public static final String KNOWN_HOSTS_FILE = "MY_KNOWN_HOSTS_FILE";
+  public static final String PASSPHRASE = "PASSPHRASE";
+
+  private String myHost;
+  private int myPort;
+  private boolean myAnonymous;
+  private String myUserName;
+  private String myPassword;
+  private boolean myUseKeyPair;
+  private String myPrivateKeyFile;
+  private String myKnownHostsFile;
+  private String myPassphrase;
+  private boolean myStorePassword;
+  private boolean myStorePassphrase;
+
+  @Override
+  public String getHost() {
+    return myHost;
+  }
+
+  public void setHost(String host) {
+    myHost = host;
+  }
+
+  @Override
+  public int getPort() {
+    return myPort;
+  }
+
+  public void setPort(int port) {
+    myPort = port;
+  }
+
+  @Override
+  @Transient
+  public String getUserName() {
+    return myUserName;
+  }
+
+  public void setUserName(String userName) {
+    myUserName = userName;
+  }
+
+  @Override
+  public String getPassword() {
+    return myPassword;
+  }
+
+  public void setPassword(String password) {
+    myPassword = password;
+  }
+
+  public void setStorePassword(boolean storePassword) {
+    myStorePassword = storePassword;
+  }
+
+  public void setStorePassphrase(boolean storePassphrase) {
+    myStorePassphrase = storePassphrase;
+  }
+
+  @Override
+  public boolean isStorePassword() {
+    return myStorePassword;
+  }
+
+  @Override
+  public boolean isStorePassphrase() {
+    return myStorePassphrase;
+  }
+
+  @Override
+  public boolean isAnonymous() {
+    return myAnonymous;
+  }
+
+  public void setAnonymous(boolean anonymous) {
+    myAnonymous = anonymous;
+  }
+
+  @Override
+  public String getPrivateKeyFile() {
+    return myPrivateKeyFile;
+  }
+
+  public void setPrivateKeyFile(String privateKeyFile) {
+    myPrivateKeyFile = privateKeyFile;
+  }
+
+  @Override
+  public String getKnownHostsFile() {
+    return myKnownHostsFile;
+  }
+
+  public void setKnownHostsFile(String knownHostsFile) {
+    myKnownHostsFile = knownHostsFile;
+  }
+
+  @Override
+  @Transient
+  public String getPassphrase() {
+    return myPassphrase;
+  }
+
+  public void setPassphrase(String passphrase) {
+    myPassphrase = passphrase;
+  }
+
+  @Override
+  public boolean isUseKeyPair() {
+    return myUseKeyPair;
+  }
+
+  public void setUseKeyPair(boolean useKeyPair) {
+    myUseKeyPair = useKeyPair;
+  }
+
+  public String getSerializedUserName() {
+    if (myAnonymous || myUserName == null) return "";
+    return myUserName;
+  }
+
+  public void setSerializedUserName(String userName) {
+    if (StringUtil.isEmpty(userName)) {
+      myUserName = null;
+    }
+    else {
+      myUserName = userName;
+    }
+  }
+
+  public String getSerializedPassword() {
+    if (myAnonymous) return "";
+
+    if (myStorePassword) {
+      return PasswordUtil.encodePassword(myPassword);
+    }
+    else {
+      return "";
+    }
+  }
+
+  public void setSerializedPassword(String serializedPassword) {
+    if (!StringUtil.isEmpty(serializedPassword)) {
+      myPassword = PasswordUtil.decodePassword(serializedPassword);
+      myStorePassword = true;
+    }
+    else {
+      myPassword = null;
+    }
+  }
+
+  @Nullable
+  public String getSerializedPassphrase() {
+    if (myStorePassphrase) {
+      return PasswordUtil.encodePassword(myPassphrase);
+    }
+    else {
+      return "";
+    }
+  }
+
+  public void setSerializedPassphrase(String serializedPassphrase) {
+    if (!StringUtil.isEmpty(serializedPassphrase)) {
+      myPassphrase = PasswordUtil.decodePassword(serializedPassphrase);
+      myStorePassphrase = true;
+    }
+    else {
+      myPassphrase = null;
+      myStorePassphrase = false;
+    }
+  }
+
+  public void copyRemoteCredentialsTo(RemoteSdkCredentials to) {
+    to.setHost(getHost());
+    to.setPort(getPort());
+    to.setAnonymous(isAnonymous());
+    to.setUserName(getUserName());
+    to.setPassword(getPassword());
+    to.setUseKeyPair(isUseKeyPair());
+    to.setPrivateKeyFile(getPrivateKeyFile());
+    to.setKnownHostsFile(getKnownHostsFile());
+    to.setStorePassword(isStorePassword());
+    to.setStorePassphrase(isStorePassphrase());
+  }
+
+  public void load(Element element) {
+    setHost(element.getAttributeValue(HOST));
+    setPort(StringUtil.parseInt(element.getAttributeValue(PORT), 22));
+    setAnonymous(StringUtil.parseBoolean(element.getAttributeValue(ANONYMOUS), false));
+    setSerializedUserName(element.getAttributeValue(USERNAME));
+    setSerializedPassword(element.getAttributeValue(PASSWORD));
+    setPrivateKeyFile(StringUtil.nullize(element.getAttributeValue(PRIVATE_KEY_FILE)));
+    setKnownHostsFile(StringUtil.nullize(element.getAttributeValue(KNOWN_HOSTS_FILE)));
+    setSerializedPassphrase(element.getAttributeValue(PASSPHRASE));
+    setUseKeyPair(StringUtil.parseBoolean(element.getAttributeValue(USE_KEY_PAIR), false));
+  }
+
+  public void save(Element rootElement) {
+    rootElement.setAttribute(HOST, StringUtil.notNullize(getHost()));
+    rootElement.setAttribute(PORT, Integer.toString(getPort()));
+    rootElement.setAttribute(ANONYMOUS, Boolean.toString(isAnonymous()));
+    rootElement.setAttribute(USERNAME, getSerializedUserName());
+    rootElement.setAttribute(PASSWORD, getSerializedPassword());
+    rootElement.setAttribute(PRIVATE_KEY_FILE, StringUtil.notNullize(getPrivateKeyFile()));
+    rootElement.setAttribute(KNOWN_HOSTS_FILE, StringUtil.notNullize(getKnownHostsFile()));
+    rootElement.setAttribute(PASSPHRASE, getSerializedPassphrase());
+    rootElement.setAttribute(USE_KEY_PAIR, Boolean.toString(isUseKeyPair()));
+  }
+
+  public void copyFrom(RemoteCredentials from) {
+    setHost(from.getHost());
+    setPort(from.getPort());
+    setAnonymous(from.isAnonymous());
+    setUserName(from.getUserName());
+    setPassword(from.getPassword());
+    setUseKeyPair(from.isUseKeyPair());
+    setPrivateKeyFile(from.getPrivateKeyFile());
+    setKnownHostsFile(from.getKnownHostsFile());
+    setStorePassword(from.isStorePassword());
+    setStorePassphrase(from.isStorePassphrase());
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteFile.java b/platform/platform-impl/src/com/intellij/remote/RemoteFile.java
new file mode 100644
index 0000000..4a2e113
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteFile.java
@@ -0,0 +1,110 @@
+package com.intellij.remote;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author traff
+ */
+public class RemoteFile {
+
+  private final boolean myWin;
+  private final String myPath;
+
+  public RemoteFile(@NotNull String path, boolean isWin) {
+    myPath = toSystemDependent(path, isWin);
+    myWin = isWin;
+  }
+
+  public RemoteFile(@NotNull String parent, String child) {
+    this(resolveChild(parent, child, isWindowsPath(parent)), isWindowsPath(parent));
+  }
+
+  public RemoteFile(@NotNull String parent, String child, boolean isWin) {
+    this(resolveChild(parent, child, isWin), isWin);
+  }
+
+  @Nullable
+  public String getName() {
+    int ind = myPath.lastIndexOf(getSeparator(myWin));
+    if (ind != -1 && ind < myPath.length() - 1) { //not last char
+      return myPath.substring(ind + 1);
+    }
+    else {
+      return null;
+    }
+  }
+
+  private static String resolveChild(@NotNull String parent, @NotNull String child, boolean win) {
+    String separator = getSeparator(win);
+
+    String path;
+    if (parent.endsWith(separator)) {
+      path = parent + child;
+    }
+    else {
+      path = parent + separator + child;
+    }
+    return path;
+  }
+
+  private static String getSeparator(boolean win) {
+    String separator;
+    if (win) {
+      separator = "\\";
+    }
+    else {
+      separator = "/";
+    }
+    return separator;
+  }
+
+
+  public String getPath() {
+    return myPath;
+  }
+
+  public boolean isWin() {
+    return isWindowsPath(myPath);
+  }
+
+  public static boolean isWindowsPath(@NotNull String path) {
+    path = RemoteSdkCredentialsHolder.getInterpreterPathFromFullPath(path);
+
+    return (path.length() > 1 && path.charAt(1) == ':');
+  }
+
+  private static String toSystemDependent(@NotNull String path, boolean isWin) {
+    char separator = isWin ? '\\' : '/';
+    return FileUtil.toSystemIndependentName(path).replace('/', separator);
+  }
+
+  public static RemoteFileBuilder detectSystemByPath(@NotNull String path) {
+    return new RemoteFileBuilder(isWindowsPath(path));
+  }
+
+  public static RemoteFile createRemoteFile(String path, String script) {
+    return detectSystemByPath(path).createRemoteFile(path, script);
+  }
+
+  public static RemoteFile createRemoteFile(final String path, final String script, final boolean isWindows) {
+    return new RemoteFileBuilder(isWindows).createRemoteFile(path, script);
+  }
+
+  public static class RemoteFileBuilder {
+    private final boolean isWin;
+
+    private RemoteFileBuilder(boolean win) {
+      isWin = win;
+    }
+
+    public RemoteFile createRemoteFile(String path) {
+      return new RemoteFile(path, isWin);
+    }
+
+    public RemoteFile createRemoteFile(String path, String child) {
+      return new RemoteFile(path, child, isWin);
+    }
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteProcessHandlerBase.java b/platform/platform-impl/src/com/intellij/remote/RemoteProcessHandlerBase.java
new file mode 100644
index 0000000..efeb9bf
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteProcessHandlerBase.java
@@ -0,0 +1,20 @@
+package com.intellij.remote;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.remote.RemoteSdkException;
+import com.intellij.util.PathMappingSettings;
+
+import java.util.List;
+
+/**
+ * @author traff
+ */
+public interface RemoteProcessHandlerBase {
+  PathMappingSettings getMappingSettings();
+
+  Pair<String, Integer> obtainRemoteSocket() throws RemoteSdkException;
+
+  void addRemoteForwarding(int remotePort, int localPort);
+
+  List<PathMappingSettings.PathMapping> getFileMappings();
+}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkAdditionalData2.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java
similarity index 71%
rename from platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkAdditionalData2.java
rename to platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java
index 92ec302..4cb6707 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkAdditionalData2.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java
@@ -13,17 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk2;
+package com.intellij.remote;
 
 import com.intellij.openapi.projectRoots.SdkAdditionalData;
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.remotesdk.RemoteSdkCredentialsHolder;
-import com.intellij.remotesdk.RemoteSdkProperties;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * @author traff
  */
-public interface RemoteSdkAdditionalData2<T extends RemoteSdkCredentials>
+public interface RemoteSdkAdditionalData<T extends RemoteSdkCredentials>
   extends SdkAdditionalData, RemoteSdkProducer<T>, RemoteSdkProperties {
   void completeInitialization();
 
@@ -33,9 +31,13 @@
 
   String getFullInterpreterPath();
 
+  void setVagrantConnectionType(@NotNull VagrantBasedCredentialsHolder vagrantBasedCredentials);
+
   /**
    * This method switches to use of ssh-credentials based data
    * @param credentials credentials that specify connection
    */
-  void setSshCredentials(RemoteSdkCredentialsHolder credentials);
+  void setSshCredentials(@NotNull RemoteCredentialsHolder credentials);
+
+  void setDeploymentConnectionType(@NotNull WebDeploymentCredentialsHolder credentials);
 }
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentials.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentials.java
new file mode 100644
index 0000000..876f827
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentials.java
@@ -0,0 +1,11 @@
+package com.intellij.remote;
+
+import com.intellij.remote.MutableRemoteCredentials;
+import com.intellij.remote.RemoteSdkProperties;
+
+/**
+ * @author traff
+ */
+public interface RemoteSdkCredentials extends MutableRemoteCredentials, RemoteSdkProperties {
+  String getFullInterpreterPath();
+}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentialsBuilder.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsBuilder.java
similarity index 98%
rename from platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentialsBuilder.java
rename to platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsBuilder.java
index 57ea113..59e9cf0 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentialsBuilder.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsBuilder.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk;
+package com.intellij.remote;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentialsHolder.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java
similarity index 67%
rename from platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentialsHolder.java
rename to platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java
index 8866359..e936686 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentialsHolder.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java
@@ -1,11 +1,9 @@
-package com.intellij.remotesdk;
+package com.intellij.remote;
 
-import com.intellij.openapi.util.text.StringUtil;
 import org.jdom.Element;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -13,11 +11,6 @@
  */
 public class RemoteSdkCredentialsHolder extends RemoteCredentialsHolder implements RemoteSdkCredentials {
   public static final String SSH_PREFIX = "ssh://";
-  private static final String INTERPRETER_PATH = "INTERPRETER_PATH";
-  private static final String HELPERS_PATH = "HELPERS_PATH";
-  private static final String REMOTE_ROOTS = "REMOTE_ROOTS";
-  private static final String REMOTE_PATH = "REMOTE_PATH";
-  private static final String INITIALIZED = "INITIALIZED";
 
   @NotNull
   private final RemoteSdkPropertiesHolder myRemoteSdkProperties;
@@ -30,7 +23,6 @@
     return SSH_PREFIX + cred.getUserName() + "@" + cred.getHost() + ":" + cred.getPort() + cred.getInterpreterPath();
   }
 
-
   /**
    * Extracts interpreter path from full path generated by method getFullInterpreterPath
    * Returns fullPath as fallback
@@ -118,7 +110,7 @@
 
   @Override
   public String getFullInterpreterPath() {
-    return myRemoteSdkProperties.getFullInterpreterPath();
+    return constructSshCredentialsSdkFullPath(this);
   }
 
   @Override
@@ -127,6 +119,11 @@
   }
 
   @Override
+  public String getSdkId() {
+    return myRemoteSdkProperties.getSdkId();
+  }
+
+  @Override
   public boolean isInitialized() {
     return myRemoteSdkProperties.isInitialized();
   }
@@ -138,64 +135,27 @@
 
   public static boolean isRemoteSdk(@Nullable String path) {
     if (path != null) {
-      return path.startsWith(SSH_PREFIX);
+      return path.startsWith(SSH_PREFIX) || path.startsWith(RemoteConnectionCredentialsWrapper.VAGRANT_PREFIX) ||
+             path.startsWith(RemoteConnectionCredentialsWrapper.SFTP_DEPLOYMENT_PREFIX);
     }
     else {
       return false;
     }
   }
 
-  public void loadRemoteSdkCredentials(Element element) {
-    setHost(element.getAttributeValue(HOST));
-    setPort(StringUtil.parseInt(element.getAttributeValue(PORT), 22));
-    setAnonymous(StringUtil.parseBoolean(element.getAttributeValue(ANONYMOUS), false));
-    setSerializedUserName(element.getAttributeValue(USERNAME));
-    setSerializedPassword(element.getAttributeValue(PASSWORD));
-    setPrivateKeyFile(StringUtil.nullize(element.getAttributeValue(PRIVATE_KEY_FILE)));
-    setKnownHostsFile(StringUtil.nullize(element.getAttributeValue(KNOWN_HOSTS_FILE)));
-    setSerializedPassphrase(element.getAttributeValue(PASSPHRASE));
-    setUseKeyPair(StringUtil.parseBoolean(element.getAttributeValue(USE_KEY_PAIR), false));
 
-    setInterpreterPath(StringUtil.nullize(element.getAttributeValue(INTERPRETER_PATH)));
-    setHelpersPath(StringUtil.nullize(element.getAttributeValue(HELPERS_PATH)));
+  @Override
+  public void load(Element element) {
+    super.load(element);
 
-    setRemoteRoots(loadStringsList(element, REMOTE_ROOTS, REMOTE_PATH));
-
-    setInitialized(StringUtil.parseBoolean(element.getAttributeValue(INITIALIZED), true));
+    myRemoteSdkProperties.load(element);
   }
 
-  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;
-  }
+  @Override
+  public void save(Element rootElement) {
+    super.save(rootElement);
 
-  public void saveRemoteSdkData(Element rootElement) {
-    rootElement.setAttribute(HOST, StringUtil.notNullize(getHost()));
-    rootElement.setAttribute(PORT, Integer.toString(getPort()));
-    rootElement.setAttribute(ANONYMOUS, Boolean.toString(isAnonymous()));
-    rootElement.setAttribute(USERNAME, getSerializedUserName());
-    rootElement.setAttribute(PASSWORD, getSerializedPassword());
-    rootElement.setAttribute(PRIVATE_KEY_FILE, StringUtil.notNullize(getPrivateKeyFile()));
-    rootElement.setAttribute(KNOWN_HOSTS_FILE, StringUtil.notNullize(getKnownHostsFile()));
-    rootElement.setAttribute(PASSPHRASE, getSerializedPassphrase());
-    rootElement.setAttribute(USE_KEY_PAIR, Boolean.toString(isUseKeyPair()));
-
-    rootElement.setAttribute(INTERPRETER_PATH, StringUtil.notNullize(getInterpreterPath()));
-    rootElement.setAttribute(HELPERS_PATH, StringUtil.notNullize(getHelpersPath()));
-
-    rootElement.setAttribute(INITIALIZED, Boolean.toString(isInitialized()));
-
-    for (String remoteRoot : getRemoteRoots()) {
-      final Element child = new Element(REMOTE_ROOTS);
-      child.setAttribute(REMOTE_PATH, remoteRoot);
-      rootElement.addContent(child);
-    }
+    myRemoteSdkProperties.save(rootElement);
   }
 
 
@@ -268,8 +228,8 @@
            '}';
   }
 
-  public void copyTo(RemoteSdkCredentialsHolder to) {
-    super.copyTo(to);
+  public void copyRemoteSdkCredentialsTo(RemoteSdkCredentialsHolder to) {
+    super.copyRemoteCredentialsTo(to);
     myRemoteSdkProperties.copyTo(to.getRemoteSdkProperties());
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkException.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkException.java
new file mode 100644
index 0000000..fd6f544
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkException.java
@@ -0,0 +1,49 @@
+package com.intellij.remote;
+
+import com.intellij.execution.ExecutionException;
+
+import java.net.NoRouteToHostException;
+
+/**
+ * @author traff
+ */
+public class RemoteSdkException extends ExecutionException {
+  private final boolean myNoRouteToHost;
+  private final boolean myAuthFailed;
+
+  public RemoteSdkException(String s, Throwable throwable) {
+    super(s, throwable);
+    myNoRouteToHost = throwable instanceof NoRouteToHostException;
+    myAuthFailed = false;
+  }
+
+  public RemoteSdkException(String s) {
+    super(s);
+    myAuthFailed = false;
+    myNoRouteToHost = false;
+  }
+
+  public boolean isNoRouteToHost() {
+    return myNoRouteToHost;
+  }
+
+  public boolean isAuthFailed() {
+    return myAuthFailed;
+  }
+
+  public String getMessage() {
+    if (myNoRouteToHost) {
+      return getCause().getMessage();
+    }
+    else if (myAuthFailed) {
+      return "Authentication failed";
+    }
+    else {
+      return super.getMessage();
+    }
+  }
+
+  public static RemoteSdkException cantObtainRemoteCredentials(Throwable e) {
+    return new RemoteSdkException("Cant obtain remote credentials", e);
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkFactory2.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkFactory.java
similarity index 85%
rename from platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkFactory2.java
rename to platform/platform-impl/src/com/intellij/remote/RemoteSdkFactory.java
index cc3d06a..dc28679 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkFactory2.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkFactory.java
@@ -13,11 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk2;
+package com.intellij.remote;
 
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.projectRoots.Sdk;
-import com.intellij.remotesdk.RemoteInterpreterException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -27,9 +26,9 @@
 /**
  * @author traff
  */
-public interface RemoteSdkFactory2<T extends RemoteSdkAdditionalData2> {
+public interface RemoteSdkFactory<T extends RemoteSdkAdditionalData> {
   Sdk createRemoteSdk(@Nullable Project project, @NotNull T data, @Nullable String sdkName, Collection<Sdk> existingSdks)
-    throws RemoteInterpreterException;
+    throws RemoteSdkException;
 
   Sdk createUnfinished(T data, Collection<Sdk> existingSdks);
 
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkProducer.java
similarity index 84%
rename from platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
rename to platform/platform-impl/src/com/intellij/remote/RemoteSdkProducer.java
index 72c585b..cd5c00e 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkProducer.java
@@ -13,9 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk2;
+package com.intellij.remote;
 
-import com.intellij.remotesdk.RemoteSdkCredentials;
 import com.intellij.util.Consumer;
 
 /**
@@ -24,7 +23,7 @@
 public interface RemoteSdkProducer<T extends RemoteSdkCredentials> {
   T getRemoteSdkCredentials() throws InterruptedException;
   
-  void produceRemoteSdkCredentials(Consumer<T> remoteSdkConsumer);
+  void produceRemoteSdkCredentials(Consumer<T> remoteSdkCredentialsConsumer);
 
   Object getRemoteSdkDataKey();
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkProperties.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java
similarity index 94%
rename from platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkProperties.java
rename to platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java
index 5e98352..7d13257 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkProperties.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk;
+package com.intellij.remote;
 
 import java.util.List;
 
@@ -43,10 +43,10 @@
 
   void setHelpersVersionChecked(boolean helpersVersionChecked);
 
-  String getFullInterpreterPath();
-
   void setSdkId(String sdkId);
 
+  String getSdkId();
+
   @Deprecated
   boolean isInitialized();
 
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkPropertiesHolder.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java
similarity index 65%
rename from platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkPropertiesHolder.java
rename to platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java
index 11f350c..bc5fad1 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkPropertiesHolder.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java
@@ -13,7 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk;
+package com.intellij.remote;
+
+import com.intellij.openapi.util.JDOMExternalizer;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -22,6 +26,12 @@
  * @author traff
  */
 public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
+  private static final String INTERPRETER_PATH = "INTERPRETER_PATH";
+  private static final String HELPERS_PATH = "HELPERS_PATH";
+  private static final String REMOTE_ROOTS = "REMOTE_ROOTS";
+  private static final String REMOTE_PATH = "REMOTE_PATH";
+  private static final String INITIALIZED = "INITIALIZED";
+
   private String mySdkId;
 
   private String myInterpreterPath;
@@ -93,15 +103,14 @@
     myHelpersVersionChecked = helpersVersionChecked;
   }
 
-  @Override
-  public String getFullInterpreterPath() {
-    return mySdkId;
-  }
-
   public void setSdkId(String sdkId) {
     mySdkId = sdkId;
   }
 
+  public String getSdkId() {
+    return mySdkId;
+  }
+
   @Override
   public boolean isInitialized() {
     return myInitialized;
@@ -113,7 +122,7 @@
 
   }
 
-  public void copyTo(RemoteSdkPropertiesHolder copy) {
+  public void copyTo(RemoteSdkProperties copy) {
     copy.setInterpreterPath(getInterpreterPath());
     copy.setHelpersPath(getHelpersPath());
     copy.setHelpersVersionChecked(isHelpersVersionChecked());
@@ -122,4 +131,26 @@
 
     copy.setInitialized(isInitialized());
   }
+
+  public void save(Element rootElement) {
+    rootElement.setAttribute(INTERPRETER_PATH, StringUtil.notNullize(getInterpreterPath()));
+    rootElement.setAttribute(HELPERS_PATH, StringUtil.notNullize(getHelpersPath()));
+
+    rootElement.setAttribute(INITIALIZED, Boolean.toString(isInitialized()));
+
+    for (String remoteRoot : getRemoteRoots()) {
+      final Element child = new Element(REMOTE_ROOTS);
+      child.setAttribute(REMOTE_PATH, remoteRoot);
+      rootElement.addContent(child);
+    }
+  }
+
+  public void load(Element element) {
+    setInterpreterPath(StringUtil.nullize(element.getAttributeValue(INTERPRETER_PATH)));
+    setHelpersPath(StringUtil.nullize(element.getAttributeValue(HELPERS_PATH)));
+
+    setRemoteRoots(JDOMExternalizer.loadStringsList(element, REMOTE_ROOTS, REMOTE_PATH));
+
+    setInitialized(StringUtil.parseBoolean(element.getAttributeValue(INITIALIZED), true));
+  }
 }
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSshProcess.java b/platform/platform-impl/src/com/intellij/remote/RemoteSshProcess.java
new file mode 100644
index 0000000..b9090bc
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSshProcess.java
@@ -0,0 +1,22 @@
+package com.intellij.remote;
+
+import com.intellij.execution.process.SelfKiller;
+
+/**
+ * @author traff
+ */
+abstract public class RemoteSshProcess extends Process implements SelfKiller {
+  /**
+   * Makes host:localPort server which is available on local side available on remote side as localhost:remotePort.
+   */
+  public abstract void addRemoteTunnel(int remotePort, String host, int localPort) throws RemoteSdkException;
+
+  /**
+   * Makes host:remotePort server which is available on remote side available on local side as localhost:localPort.
+   */
+  public abstract void addLocalTunnel(int localPort, String host, int remotePort) throws RemoteSdkException;
+
+  public abstract boolean hasPty();
+
+  public abstract boolean sendCtrlC();
+}
diff --git a/platform/platform-impl/src/com/intellij/remote/VagrantBasedCredentialsHolder.java b/platform/platform-impl/src/com/intellij/remote/VagrantBasedCredentialsHolder.java
new file mode 100644
index 0000000..d5f867c
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/VagrantBasedCredentialsHolder.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.remote;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+/**
+* @author traff
+*/
+public class VagrantBasedCredentialsHolder {
+  private static final String VAGRANT_FOLDER = "VAGRANT_FOLDER";
+  private String myVagrantFolder;
+
+  public VagrantBasedCredentialsHolder() {
+  }
+
+  public VagrantBasedCredentialsHolder(@NotNull String folder) {
+    myVagrantFolder = folder;
+  }
+
+  public void setVagrantFolder(String vagrantFolder) {
+    myVagrantFolder = vagrantFolder;
+  }
+
+  @NotNull
+  public String getVagrantFolder() {
+    return myVagrantFolder;
+  }
+
+  public void load(Element element) {
+    setVagrantFolder(element.getAttributeValue(VAGRANT_FOLDER));
+  }
+
+  public void save(Element element) {
+    element.setAttribute(VAGRANT_FOLDER, getVagrantFolder());
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remote/WebDeploymentCredentialsHolder.java b/platform/platform-impl/src/com/intellij/remote/WebDeploymentCredentialsHolder.java
new file mode 100644
index 0000000..5db969a
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/remote/WebDeploymentCredentialsHolder.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.remote;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author traff
+ */
+public class WebDeploymentCredentialsHolder {
+  public static final String WEB_SERVER_CONFIG_ID = "WEB_SERVER_CONFIG_ID";
+
+  private String myWebServerConfigId;
+  private final RemoteCredentialsHolder myRemoteCredentials = new RemoteCredentialsHolder();
+
+
+  public WebDeploymentCredentialsHolder() {
+  }
+
+  public WebDeploymentCredentialsHolder(@NotNull String webServerConfigId, @NotNull RemoteCredentials remoteCredentials) {
+    myWebServerConfigId = webServerConfigId;
+    myRemoteCredentials.copyFrom(remoteCredentials);
+  }
+
+  @NotNull
+  public String getWebServerConfigId() {
+    return myWebServerConfigId;
+  }
+
+  public void setWebServerConfigId(@NotNull String webServerConfigId) {
+    myWebServerConfigId = webServerConfigId;
+  }
+
+  public void load(Element element) {
+    myRemoteCredentials.load(element);
+    setWebServerConfigId(element.getAttributeValue(WEB_SERVER_CONFIG_ID));
+  }
+
+  public void save(Element element) {
+    element.setAttribute(WEB_SERVER_CONFIG_ID, getWebServerConfigId());
+
+    myRemoteCredentials.save(element);
+  }
+
+  public RemoteCredentials getSshCredentials() {
+    return myRemoteCredentials;
+  }
+}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/MutableRemoteCredentials.java b/platform/platform-impl/src/com/intellij/remotesdk/MutableRemoteCredentials.java
index e52d8d3..0b630fe 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/MutableRemoteCredentials.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/MutableRemoteCredentials.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.
@@ -15,31 +15,9 @@
  */
 package com.intellij.remotesdk;
 
-import org.jetbrains.annotations.Nullable;
-
 /**
+ * @deprecated Remove in IDEA 14
  * @author traff
  */
-public interface MutableRemoteCredentials extends RemoteCredentials {
-  void setHost(String host);
-
-  void setPort(int port);
-
-  void setUserName(String userName);
-
-  void setPassword(@Nullable String password);
-
-  void setStorePassword(boolean storePassword);
-
-  void setStorePassphrase(boolean storePassphrase);
-
-  void setAnonymous(boolean anonymous);
-
-  void setPrivateKeyFile(String privateKeyFile);
-
-  void setKnownHostsFile(String knownHostsFile);
-
-  void setPassphrase(@Nullable String passphrase);
-
-  void setUseKeyPair(boolean useKeyPair);
+public interface MutableRemoteCredentials extends com.intellij.remote.MutableRemoteCredentials {
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCancelledException.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteCancelledException.java
index eeded52..2a24920 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCancelledException.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteCancelledException.java
@@ -1,9 +1,26 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.remotesdk;
 
 /**
+ * @deprecated Remove in IDEA 14
+ * 
  * @author traff
  */
-public class RemoteCancelledException extends RemoteInterpreterException {
+public class RemoteCancelledException extends com.intellij.remote.RemoteCancelledException {
   public RemoteCancelledException(String s) {
     super(s);
   }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentials.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentials.java
index bb74940..e6be766 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentials.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentials.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.
@@ -15,33 +15,10 @@
  */
 package com.intellij.remotesdk;
 
-import com.intellij.util.xmlb.annotations.Transient;
-
 /**
+ * @deprecated Remove in IDEA 14
+ * 
  * @author traff
  */
-public interface RemoteCredentials {
-  String getHost();
-
-  int getPort();
-
-  @Transient
-  String getUserName();
-
-  String getPassword();
-
-  @Transient
-  String getPassphrase();
-
-  boolean isUseKeyPair();
-
-  boolean isAnonymous();
-
-  String getPrivateKeyFile();
-
-  boolean isStorePassword();
-
-  boolean isStorePassphrase();
-
-  String getKnownHostsFile();
+public interface RemoteCredentials extends com.intellij.remote.RemoteCredentials {
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentialsHolder.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentialsHolder.java
index d0e7e97..8860529 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentialsHolder.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentialsHolder.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.
@@ -15,205 +15,10 @@
  */
 package com.intellij.remotesdk;
 
-import com.intellij.openapi.util.PasswordUtil;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.xmlb.annotations.Transient;
-import org.jetbrains.annotations.Nullable;
-
 /**
- * @author michael.golubev
+ * @deprecated Remove in IDEA 14
+ * 
+ * @author traff
  */
-public class RemoteCredentialsHolder implements MutableRemoteCredentials {
-
-  public static final String HOST = "HOST";
-  public static final String PORT = "PORT";
-  public static final String ANONYMOUS = "ANONYMOUS";
-  public static final String USERNAME = "USERNAME";
-  public static final String PASSWORD = "PASSWORD";
-  public static final String USE_KEY_PAIR = "USE_KEY_PAIR";
-  public static final String PRIVATE_KEY_FILE = "PRIVATE_KEY_FILE";
-  public static final String KNOWN_HOSTS_FILE = "MY_KNOWN_HOSTS_FILE";
-  public static final String PASSPHRASE = "PASSPHRASE";
-
-  private String myHost;
-  private int myPort;
-  private boolean myAnonymous;
-  private String myUserName;
-  private String myPassword;
-  private boolean myUseKeyPair;
-  private String myPrivateKeyFile;
-  private String myKnownHostsFile;
-  private String myPassphrase;
-  private boolean myStorePassword;
-  private boolean myStorePassphrase;
-
-  @Override
-  public String getHost() {
-    return myHost;
-  }
-
-  public void setHost(String host) {
-    myHost = host;
-  }
-
-  @Override
-  public int getPort() {
-    return myPort;
-  }
-
-  public void setPort(int port) {
-    myPort = port;
-  }
-
-  @Override
-  @Transient
-  public String getUserName() {
-    return myUserName;
-  }
-
-  public void setUserName(String userName) {
-    myUserName = userName;
-  }
-
-  @Override
-  public String getPassword() {
-    return myPassword;
-  }
-
-  public void setPassword(String password) {
-    myPassword = password;
-  }
-
-  public void setStorePassword(boolean storePassword) {
-    myStorePassword = storePassword;
-  }
-
-  public void setStorePassphrase(boolean storePassphrase) {
-    myStorePassphrase = storePassphrase;
-  }
-
-  @Override
-  public boolean isStorePassword() {
-    return myStorePassword;
-  }
-
-  @Override
-  public boolean isStorePassphrase() {
-    return myStorePassphrase;
-  }
-
-  @Override
-  public boolean isAnonymous() {
-    return myAnonymous;
-  }
-
-  public void setAnonymous(boolean anonymous) {
-    myAnonymous = anonymous;
-  }
-
-  @Override
-  public String getPrivateKeyFile() {
-    return myPrivateKeyFile;
-  }
-
-  public void setPrivateKeyFile(String privateKeyFile) {
-    myPrivateKeyFile = privateKeyFile;
-  }
-
-  @Override
-  public String getKnownHostsFile() {
-    return myKnownHostsFile;
-  }
-
-  public void setKnownHostsFile(String knownHostsFile) {
-    myKnownHostsFile = knownHostsFile;
-  }
-
-  @Override
-  @Transient
-  public String getPassphrase() {
-    return myPassphrase;
-  }
-
-  public void setPassphrase(String passphrase) {
-    myPassphrase = passphrase;
-  }
-
-  @Override
-  public boolean isUseKeyPair() {
-    return myUseKeyPair;
-  }
-
-  public void setUseKeyPair(boolean useKeyPair) {
-    myUseKeyPair = useKeyPair;
-  }
-
-  public String getSerializedUserName() {
-    if (myAnonymous || myUserName == null) return "";
-    return myUserName;
-  }
-
-  public void setSerializedUserName(String userName) {
-    if (StringUtil.isEmpty(userName)) {
-      myUserName = null;
-    }
-    else {
-      myUserName = userName;
-    }
-  }
-
-  public String getSerializedPassword() {
-    if (myAnonymous) return "";
-
-    if (myStorePassword) {
-      return PasswordUtil.encodePassword(myPassword);
-    }
-    else {
-      return "";
-    }
-  }
-
-  public void setSerializedPassword(String serializedPassword) {
-    if (!StringUtil.isEmpty(serializedPassword)) {
-      myPassword = PasswordUtil.decodePassword(serializedPassword);
-      myStorePassword = true;
-    }
-    else {
-      myPassword = null;
-    }
-  }
-
-  @Nullable
-  public String getSerializedPassphrase() {
-    if (myStorePassphrase) {
-      return PasswordUtil.encodePassword(myPassphrase);
-    }
-    else {
-      return "";
-    }
-  }
-
-  public void setSerializedPassphrase(String serializedPassphrase) {
-    if (!StringUtil.isEmpty(serializedPassphrase)) {
-      myPassphrase = PasswordUtil.decodePassword(serializedPassphrase);
-      myStorePassphrase = true;
-    }
-    else {
-      myPassphrase = null;
-      myStorePassphrase = false;
-    }
-  }
-
-  public void copyTo(RemoteSdkCredentials to) {
-    to.setHost(getHost());
-    to.setPort(getPort());
-    to.setAnonymous(isAnonymous());
-    to.setUserName(getUserName());
-    to.setPassword(getPassword());
-    to.setUseKeyPair(isUseKeyPair());
-    to.setPrivateKeyFile(getPrivateKeyFile());
-    to.setKnownHostsFile(getKnownHostsFile());
-    to.setStorePassword(isStorePassword());
-    to.setStorePassphrase(isStorePassphrase());
-  }
+public class RemoteCredentialsHolder extends com.intellij.remote.RemoteCredentialsHolder {
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteFile.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteFile.java
index 51896db..73274cc 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteFile.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteFile.java
@@ -1,110 +1,38 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.remotesdk;
 
-import com.intellij.openapi.util.io.FileUtil;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 /**
+ * @deprecated Remove in IDEA 14
+ * 
  * @author traff
  */
-public class RemoteFile {
-
-  private final boolean myWin;
-  private final String myPath;
+public class RemoteFile extends com.intellij.remote.RemoteFile {
 
   public RemoteFile(@NotNull String path, boolean isWin) {
-    myPath = toSystemDependent(path, isWin);
-    myWin = isWin;
+    super(path, isWin);
   }
 
   public RemoteFile(@NotNull String parent, String child) {
-    this(resolveChild(parent, child, isWindowsPath(parent)), isWindowsPath(parent));
+    super(parent, child);
   }
 
   public RemoteFile(@NotNull String parent, String child, boolean isWin) {
-    this(resolveChild(parent, child, isWin), isWin);
-  }
-
-  @Nullable
-  public String getName() {
-    int ind = myPath.lastIndexOf(getSeparator(myWin));
-    if (ind != -1 && ind < myPath.length() - 1) { //not last char
-      return myPath.substring(ind + 1);
-    }
-    else {
-      return null;
-    }
-  }
-
-  private static String resolveChild(@NotNull String parent, @NotNull String child, boolean win) {
-    String separator = getSeparator(win);
-
-    String path;
-    if (parent.endsWith(separator)) {
-      path = parent + child;
-    }
-    else {
-      path = parent + separator + child;
-    }
-    return path;
-  }
-
-  private static String getSeparator(boolean win) {
-    String separator;
-    if (win) {
-      separator = "\\";
-    }
-    else {
-      separator = "/";
-    }
-    return separator;
-  }
-
-
-  public String getPath() {
-    return myPath;
-  }
-
-  public boolean isWin() {
-    return isWindowsPath(myPath);
-  }
-
-  public static boolean isWindowsPath(@NotNull String path) {
-    path = RemoteSdkCredentialsHolder.getInterpreterPathFromFullPath(path);
-
-    return (path.length() > 1 && path.charAt(1) == ':');
-  }
-
-  private static String toSystemDependent(@NotNull String path, boolean isWin) {
-    char separator = isWin ? '\\' : '/';
-    return FileUtil.toSystemIndependentName(path).replace('/', separator);
-  }
-
-  public static RemoteFileBuilder detectSystemByPath(@NotNull String path) {
-    return new RemoteFileBuilder(isWindowsPath(path));
-  }
-
-  public static RemoteFile createRemoteFile(String path, String script) {
-    return detectSystemByPath(path).createRemoteFile(path, script);
-  }
-
-  public static RemoteFile createRemoteFile(final String path, final String script, final boolean isWindows) {
-    return new RemoteFileBuilder(isWindows).createRemoteFile(path, script);
-  }
-
-  public static class RemoteFileBuilder {
-    private final boolean isWin;
-
-    private RemoteFileBuilder(boolean win) {
-      isWin = win;
-    }
-
-    public RemoteFile createRemoteFile(String path) {
-      return new RemoteFile(path, isWin);
-    }
-
-    public RemoteFile createRemoteFile(String path, String child) {
-      return new RemoteFile(path, child, isWin);
-    }
+    super(parent, child, isWin);
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteInterpreterException.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteInterpreterException.java
index 0a31e65..b3d3b35 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteInterpreterException.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteInterpreterException.java
@@ -1,49 +1,29 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.remotesdk;
 
-import com.intellij.execution.ExecutionException;
-
-import java.net.NoRouteToHostException;
+import com.intellij.remote.RemoteSdkException;
 
 /**
+ * @deprecated Remove in IDEA 14
+ * 
  * @author traff
  */
-public class RemoteInterpreterException extends ExecutionException {
-  private final boolean myNoRouteToHost;
-  private final boolean myAuthFailed;
-
+public class RemoteInterpreterException extends RemoteSdkException {
   public RemoteInterpreterException(String s, Throwable throwable) {
     super(s, throwable);
-    myNoRouteToHost = throwable instanceof NoRouteToHostException;
-    myAuthFailed = false;
-  }
-
-  public RemoteInterpreterException(String s) {
-    super(s);
-    myAuthFailed = false;
-    myNoRouteToHost = false;
-  }
-
-  public boolean isNoRouteToHost() {
-    return myNoRouteToHost;
-  }
-
-  public boolean isAuthFailed() {
-    return myAuthFailed;
-  }
-
-  public String getMessage() {
-    if (myNoRouteToHost) {
-      return getCause().getMessage();
-    }
-    else if (myAuthFailed) {
-      return "Authentication failed";
-    }
-    else {
-      return super.getMessage();
-    }
-  }
-
-  public static RemoteInterpreterException cantObtainRemoteCredentials(Throwable e) {
-    return new RemoteInterpreterException("Cant obtain remote credentials", e);
   }
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteProcessHandlerBase.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteProcessHandlerBase.java
index c004f8a..a83d2bd 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteProcessHandlerBase.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteProcessHandlerBase.java
@@ -1,19 +1,24 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.remotesdk;
 
-import com.intellij.openapi.util.Pair;
-import com.intellij.util.PathMappingSettings;
-
-import java.util.List;
-
 /**
+ * @deprecated Remove in IDEA 14
+ * 
  * @author traff
  */
-public interface RemoteProcessHandlerBase {
-  PathMappingSettings getMappingSettings();
-
-  Pair<String, Integer> obtainRemoteSocket() throws RemoteInterpreterException;
-
-  void addRemoteForwarding(int remotePort, int localPort);
-
-  List<PathMappingSettings.PathMapping> getFileMappings();
+public interface RemoteProcessHandlerBase extends com.intellij.remote.RemoteProcessHandlerBase {
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkAdditionalData.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkAdditionalData.java
index d9f1b67..e4c79ed 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkAdditionalData.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkAdditionalData.java
@@ -1,8 +1,10 @@
 package com.intellij.remotesdk;
 
 import com.intellij.openapi.projectRoots.SdkAdditionalData;
+import com.intellij.remote.RemoteSdkCredentials;
 
 /**
+ * @deprecated Remove in IDEA 14
  * @author traff
  */
 public interface RemoteSdkAdditionalData extends RemoteSdkCredentials, SdkAdditionalData {
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentials.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentials.java
deleted file mode 100644
index 11f14f0..0000000
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkCredentials.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.intellij.remotesdk;
-
-/**
- * @author traff
- */
-public interface RemoteSdkCredentials extends MutableRemoteCredentials, RemoteSdkProperties {
-}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkData.java
similarity index 63%
copy from platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
copy to platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkData.java
index 72c585b..d99ea33 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkData.java
@@ -13,18 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk2;
+package com.intellij.remotesdk;
 
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.util.Consumer;
+import com.intellij.remote.RemoteSdkCredentials;
 
 /**
+ * @deprecated Remove in IDEA 14
+ * 
  * @author traff
  */
-public interface RemoteSdkProducer<T extends RemoteSdkCredentials> {
-  T getRemoteSdkCredentials() throws InterruptedException;
-  
-  void produceRemoteSdkCredentials(Consumer<T> remoteSdkConsumer);
-
-  Object getRemoteSdkDataKey();
+public interface RemoteSdkData extends RemoteSdkCredentials {
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataBuilder.java
similarity index 63%
copy from platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
copy to platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataBuilder.java
index 72c585b..f2dd265 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataBuilder.java
@@ -13,18 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk2;
+package com.intellij.remotesdk;
 
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.util.Consumer;
+import com.intellij.remote.RemoteSdkCredentialsBuilder;
 
 /**
+ * @deprecated Remove in IDEA 14
+ * 
  * @author traff
  */
-public interface RemoteSdkProducer<T extends RemoteSdkCredentials> {
-  T getRemoteSdkCredentials() throws InterruptedException;
-  
-  void produceRemoteSdkCredentials(Consumer<T> remoteSdkConsumer);
-
-  Object getRemoteSdkDataKey();
+public class RemoteSdkDataBuilder extends RemoteSdkCredentialsBuilder {
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataHolder.java
similarity index 63%
copy from platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
copy to platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataHolder.java
index 72c585b..b4f837c 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk2/RemoteSdkProducer.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataHolder.java
@@ -13,18 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.intellij.remotesdk2;
+package com.intellij.remotesdk;
 
-import com.intellij.remotesdk.RemoteSdkCredentials;
-import com.intellij.util.Consumer;
+import com.intellij.remote.RemoteSdkCredentialsHolder;
+import org.jetbrains.annotations.NotNull;
 
 /**
+ * @deprecated Remove in IDEA 14
+ * 
  * @author traff
  */
-public interface RemoteSdkProducer<T extends RemoteSdkCredentials> {
-  T getRemoteSdkCredentials() throws InterruptedException;
-  
-  void produceRemoteSdkCredentials(Consumer<T> remoteSdkConsumer);
-
-  Object getRemoteSdkDataKey();
+public class RemoteSdkDataHolder extends RemoteSdkCredentialsHolder {
+  public RemoteSdkDataHolder(@NotNull String defaultHelpersDirName) {
+    super(defaultHelpersDirName);
+  }
 }
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkFactory.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkFactory.java
index 86113a5..1934d1a 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkFactory.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkFactory.java
@@ -17,6 +17,7 @@
 
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.remote.RemoteSdkException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -24,6 +25,7 @@
 import java.util.Collection;
 
 /**
+ * @deprecated Remove in IDEA 14
  * @author traff
  */
 public interface RemoteSdkFactory<T extends RemoteSdkAdditionalData> {
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSshProcess.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSshProcess.java
index 35c5897..3abe39b 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSshProcess.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSshProcess.java
@@ -1,22 +1,23 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.remotesdk;
 
-import com.intellij.execution.process.SelfKiller;
-
 /**
+ * @deprecated Remove in IDEA 14
  * @author traff
  */
-abstract public class RemoteSshProcess extends Process implements SelfKiller {
-  /**
-   * Makes host:localPort server which is available on local side available on remote side as localhost:remotePort.
-   */
-  public abstract void addRemoteTunnel(int remotePort, String host, int localPort) throws RemoteInterpreterException;
-
-  /**
-   * Makes host:remotePort server which is available on remote side available on local side as localhost:localPort.
-   */
-  public abstract void addLocalTunnel(int localPort, String host, int remotePort) throws RemoteInterpreterException;
-
-  public abstract boolean hasPty();
-
-  public abstract boolean sendCtrlC();
+public abstract class RemoteSshProcess extends com.intellij.remote.RemoteSshProcess {
 }
diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
index c3ba3a3..0070cb0 100644
--- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
+++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.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.
@@ -206,6 +206,7 @@
     if (!myEnabled) return;
 
     if (selected == null
+        || !myComponent.isEnabled()
         || !myComponent.isShowing()
         || !myComponent.isFocusOwner() && !processIfUnfocused
         || isPopup()) {
diff --git a/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java b/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java
index 4797051..411186c 100644
--- a/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java
+++ b/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java
@@ -7,6 +7,7 @@
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.ide.CopyPasteManager;
+import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -423,7 +424,7 @@
         ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
           @Override
           public void run() {
-            ApplicationManager.getApplication().runReadAction(new Runnable() {
+            DumbService.getInstance(getProject()).runReadActionInSmartMode(new Runnable() {
               @Override
               public void run() {
                 try {
diff --git a/platform/platform-impl/src/com/intellij/ui/SystemNotifications.java b/platform/platform-impl/src/com/intellij/ui/SystemNotifications.java
index 08e3863..b0d7b37 100644
--- a/platform/platform-impl/src/com/intellij/ui/SystemNotifications.java
+++ b/platform/platform-impl/src/com/intellij/ui/SystemNotifications.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -15,6 +15,8 @@
  */
 package com.intellij.ui;
 
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.components.ServiceManager;
 import org.jetbrains.annotations.NotNull;
 
@@ -22,8 +24,14 @@
  * @author mike
  */
 public abstract class SystemNotifications {
+  private static final SystemNotifications NULL = new SystemNotifications() {
+    @Override
+    public void notify(@NotNull String notificationName, @NotNull String title, @NotNull String text) { }
+  };
+
   public static SystemNotifications getInstance() {
-    return ServiceManager.getService(SystemNotifications.class);
+    Application app = ApplicationManager.getApplication();
+    return app.isHeadlessEnvironment() || app.isUnitTestMode() ? NULL : ServiceManager.getService(SystemNotifications.class);
   }
 
   public abstract void notify(@NotNull String notificationName, @NotNull String title, @NotNull String text);
diff --git a/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java b/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java
index 597301b..d81ea58 100644
--- a/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -83,7 +83,13 @@
       }
     }
     catch (Throwable t) {
-      Logger.getInstance(SystemNotifications.class).error(t);
+      Logger logger = Logger.getInstance(SystemNotifications.class);
+      if (logger.isDebugEnabled()) {
+        logger.debug(t);
+      }
+      else {
+        logger.info(t.getMessage());
+      }
     }
 
     return null;
diff --git a/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java b/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java
index aac44fc..1bee208 100755
--- a/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java
+++ b/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java
@@ -20,13 +20,13 @@
 import com.intellij.ui.Gray;
 import com.intellij.ui.JBColor;
 import com.intellij.util.ui.UIUtil;
+import org.jdesktop.swingx.graphics.GraphicsUtilities;
+import org.jdesktop.swingx.graphics.ShadowRenderer;
 
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
-import java.awt.geom.Area;
 import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
 import java.awt.image.BufferedImage;
 
 /**
@@ -45,9 +45,19 @@
   private JButton[] buttons;
   private JButton myDefaultButton;
   private JButton myFocusedButton;
+
+  public int SHADOW_BORDER = 10;
+
+  // SHEET
   public int SHEET_WIDTH = 400;
+
   public int SHEET_HEIGHT = 150;
 
+  // SHEET + shadow
+  int SHEET_NC_WIDTH = SHEET_WIDTH + SHADOW_BORDER * 2;
+  int SHEET_NC_HEIGHT = SHEET_HEIGHT + SHADOW_BORDER ;
+
+
   private Icon myIcon = AllIcons.Logo_welcomeScreen;
 
   private String myResult;
@@ -151,9 +161,11 @@
         g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.95f));
 
         g2d.setColor(Gray._225);
-        Rectangle2D dialog  = new Rectangle2D.Double(0,0,mySheetPanel.getBounds().width - 5, mySheetPanel.getBounds().height - 10);
+        Rectangle2D dialog  = new Rectangle2D.Double(SHADOW_BORDER, 0, SHEET_WIDTH, SHEET_HEIGHT);
+
+        paintShadow(g2d);
+        // draw the sheet background
         g2d.fill(dialog);
-        paintShadow(g2d, dialog);
       }
 
     };
@@ -211,21 +223,30 @@
 
 
     SHEET_HEIGHT = 20 + headerLabel.getPreferredSize().height + 10 + messageArea.height + 10 + 70;
-    sheetPanel.setSize(SHEET_WIDTH, SHEET_HEIGHT);
+
 
     ico.setOpaque(false);
     ico.setSize(new Dimension(AllIcons.Logo_welcomeScreen.getIconWidth(), AllIcons.Logo_welcomeScreen.getIconHeight()));
-    ico.setLocation(20, 20);
+    ico.setLocation(40, 20);
     sheetPanel.add(ico);
-    headerLabel.setLocation(120, 20);
-    messageTextPane.setLocation(120, 20 + headerLabel.getPreferredSize().height + 10);
+    headerLabel.setLocation(140, 20);
+    messageTextPane.setLocation(140, 20 + headerLabel.getPreferredSize().height + 10);
     layoutWithAbsoluteLayout(buttons, sheetPanel);
 
     sheetPanel.setFocusCycleRoot(true);
 
+    recalculateShadow();
+
+    sheetPanel.setSize(SHEET_NC_WIDTH, SHEET_NC_HEIGHT );
+
     return sheetPanel;
   }
 
+  private void recalculateShadow() {
+    SHEET_NC_WIDTH = SHEET_WIDTH + SHADOW_BORDER * 2;
+    SHEET_NC_HEIGHT = SHEET_HEIGHT + SHADOW_BORDER;
+  }
+
   private void layoutWithAbsoluteLayout(JButton[] buttons, JPanel sheetPanel) {
     layoutButtons(buttons, sheetPanel);
 
@@ -235,31 +256,33 @@
     }
   }
 
-  private void paintShadow(Graphics2D g2d, Rectangle2D dialog) {
-    Area shadow = new Area(new RoundRectangle2D.Double(0, 0, mySheetPanel.getBounds().width, mySheetPanel.getBounds().height, 10, 10));
+  private void paintShadow(Graphics2D g2d) {
+    BufferedImage bufferedImage = GraphicsUtilities.createCompatibleTranslucentImage(
+      SHEET_WIDTH, SHEET_HEIGHT);
 
-    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.80f));
+    Graphics2D g2 = bufferedImage.createGraphics();
+    g2.setColor(JBColor.WHITE);
+    g2.fillRoundRect(0, 0, SHEET_WIDTH - 1, SHEET_HEIGHT - 1, SHADOW_BORDER, SHADOW_BORDER);
+    g2.dispose();
 
-    Color color1 = Gray._130;
-    Color color2 = new JBColor(new Color(130, 130, 130, 0), new Color(130, 130, 130, 0));
-
-    GradientPaint gp = new GradientPaint(
-      0, mySheetPanel.getBounds().height - 10, color1,
-      0, mySheetPanel.getBounds().height, color2 );
-
-    g2d.setPaint(gp);
-    shadow.subtract(new Area(dialog));
-    g2d.fill(shadow);
+    ShadowRenderer renderer = new ShadowRenderer();
+    renderer.setSize(SHADOW_BORDER);
+    renderer.setOpacity(0.95f);
+    renderer.setColor(JBColor.BLACK);
+    BufferedImage shadow = renderer.createShadow(bufferedImage);
+    g2d.drawImage(shadow, 0, - SHADOW_BORDER, null);
+    g2d.setBackground(new JBColor(new Color(255, 255, 255, 0), new Color(255, 255, 255, 0)));
+    g2d.clearRect(SHADOW_BORDER, 0, SHEET_WIDTH, SHEET_HEIGHT);
   }
 
   private void layoutButtons(final JButton[] buttons, JPanel panel) {
 
-    int buttonsWidth = 120;
+    int buttonsWidth = 15 * 2;
 
     for (JButton button : buttons) {
       panel.add(button);
       button.repaint();
-      buttonsWidth = button.getWidth() + 10;
+      buttonsWidth += button.getPreferredSize().width + 10;
     }
 
     SHEET_WIDTH = Math.max(buttonsWidth, SHEET_WIDTH);
@@ -298,7 +321,7 @@
     myOffScreenFrame.add(mySheetPanel);
     myOffScreenFrame.getRootPane().setDefaultButton(myDefaultButton);
 
-    final BufferedImage image = UIUtil.createImage(SHEET_WIDTH, SHEET_HEIGHT, BufferedImage.TYPE_INT_ARGB);
+    final BufferedImage image = UIUtil.createImage(SHEET_NC_WIDTH, SHEET_NC_HEIGHT, BufferedImage.TYPE_INT_ARGB);
 
     mySheetPanel.paint(image.createGraphics());
     myOffScreenFrame.dispose();
diff --git a/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java b/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java
index e90078a..f2249ad 100755
--- a/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java
+++ b/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java
@@ -54,13 +54,14 @@
       @Override
       public void paint(Graphics g) {
         super.paint(g);
+
       }
     };
 
     myParent = owner;
 
     myWindow.setUndecorated(true);
-    myWindow.setBackground(new JBColor(new Color(0, 0, 0, 0), new Color(0, 0, 0, 0)));
+   myWindow.setBackground(new JBColor(new Color(0, 0, 0, 0), new Color(0, 0, 0, 0)));
     myController = new SheetController(this, title, message, icon, buttons, defaultButton, doNotAskOption, focusedButton);
 
 
@@ -70,7 +71,7 @@
     myWindow.setFocusable(true);
 
     startAnimation(true);
-    myWindow.setSize(myController.SHEET_WIDTH, myController.SHEET_HEIGHT);
+    myWindow.setSize(myController.SHEET_NC_WIDTH, myController.SHEET_NC_HEIGHT);
     restoreFullscreenButton = couldBeInFullScreen();
     if (restoreFullscreenButton) {
       FullScreenUtilities.setWindowCanFullScreen(myParent, false);
@@ -108,24 +109,24 @@
 
           int imageCropOffset = (UIUtil.isRetina()) ? imageHeight * 2 : imageHeight;
 
-          g.drawImage(staticImage, 0,0,myController.SHEET_WIDTH,imageHeight,
+          g.drawImage(staticImage, 0, 0, myController.SHEET_NC_WIDTH,imageHeight,
                       0, staticImage.getHeight(null) - imageCropOffset,
                       staticImage.getWidth(null) ,staticImage.getHeight(null) ,null);
         }
       }
     };
     staticPanel.setOpaque(false);
-    staticPanel.setSize(myController.SHEET_WIDTH,myController.SHEET_HEIGHT);
+    staticPanel.setSize(myController.SHEET_NC_WIDTH,myController.SHEET_NC_HEIGHT);
     myWindow.setContentPane(staticPanel);
 
-    Animator myAnimator = new Animator("Roll Down Sheet Animator", myController.SHEET_HEIGHT ,
+    Animator myAnimator = new Animator("Roll Down Sheet Animator", myController.SHEET_NC_HEIGHT ,
                                        TIME_TO_SHOW_SHEET, false) {
       @Override
       public void paintNow(int frame, int totalFrames, int cycle) {
         setPositionRelativeToParent();
         float percentage = (float)frame/(float)totalFrames;
-        imageHeight = enlarge ? (int)(((float)myController.SHEET_HEIGHT) * percentage):
-                      (int)(myController.SHEET_HEIGHT - percentage * myController.SHEET_HEIGHT);
+        imageHeight = enlarge ? (int)(((float)myController.SHEET_NC_HEIGHT) * percentage):
+                      (int)(myController.SHEET_NC_HEIGHT - percentage * myController.SHEET_HEIGHT);
         myWindow.repaint();
       }
 
@@ -133,9 +134,10 @@
       protected void paintCycleEnd() {
         setPositionRelativeToParent();
         if (enlarge) {
-          imageHeight = myController.SHEET_HEIGHT;
+          imageHeight = myController.SHEET_NC_HEIGHT;
           staticImage = null;
           myWindow.setContentPane(myController.getPanel(myWindow));
+
           myController.requestFocus();
         } else {
           if (restoreFullscreenButton) {
@@ -152,8 +154,11 @@
 
   private void setPositionRelativeToParent () {
     int width = myParent.getWidth();
-    myWindow.setLocation(width / 2 - myController.SHEET_WIDTH / 2 + myParent.getLocation().x,
-                         myParent.getInsets().top + myParent.getLocation().y);
+    myWindow.setBounds(width / 2 - myController.SHEET_NC_WIDTH / 2 + myParent.getLocation().x,
+                       myParent.getInsets().top + myParent.getLocation().y,
+                       myController.SHEET_NC_WIDTH,
+                       myController.SHEET_NC_HEIGHT);
+
   }
 
   private void registerMoveResizeHandler () {
diff --git a/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java b/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java
index cf1104a..51ebd5e 100644
--- a/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java
+++ b/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java
@@ -20,6 +20,8 @@
 import org.jetbrains.annotations.TestOnly;
 import org.jetbrains.io.BuiltInServer;
 
+import java.util.Random;
+import java.util.UUID;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -39,11 +41,12 @@
   private BuiltInServer server;
   private boolean enabledInUnitTestMode = true;
 
-  //static {
-  //  // IDEA-120811
-  //  System.setProperty("io.netty.machineId", Integer.toHexString(new Random().nextInt()));
-  //  System.setProperty("io.netty.processId", "1");
-  //}
+  static {
+    // IDEA-120811
+    String id = UUID.randomUUID().toString();
+    System.setProperty("io.netty.machineId", id.substring(id.length() - 8));
+    System.setProperty("io.netty.processId", Integer.toString(new Random().nextInt(65535)));
+  }
 
   @Override
   public int getPort() {
diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties
index 8d51e6b..79c6129 100644
--- a/platform/platform-resources-en/src/messages/ActionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties
@@ -107,8 +107,9 @@
 action.EditorMoveDownAndScrollWithSelection.text=Move Down and Scroll with Selection
 action.EditorCloneCaretBelow.text=Clone Caret Below
 action.EditorCloneCaretAbove.text=Clone Caret Above
-action.SelectNextOccurence.text=Select Next Occurence
-action.UnselectLastOccurence.text=Unselect Last Occurence
+action.SelectNextOccurrence.text=Select Next Occurrence
+action.SelectAllOccurrences.text=Select All Occurrences
+action.UnselectPreviousOccurrence.text=Unselect Occurrence
 action.EditorToggleStickySelection.text=Toggle Sticky Selection
 action.EditorSwapSelectionBoundaries.text=Swap selection boundaries
 action.EditorLineStart.text=Move Caret to Line Start
@@ -910,7 +911,10 @@
 action.XDebugger.JumpToTypeSource.text=Jump To Type Source
 action.XDebugger.JumpToTypeSource.description=Open source of the selected value's type
 action.XDebugger.Inspect.text=Inspect...
-action.XDebugger.AddToWatches.text=Add to Watches
+
+action.Debugger.Tree.AddToWatches.text=Add to Watches
+action.Debugger.Tree.EvaluateInConsole.text=Evaluate In Console
+
 action.XDebugger.RemoveWatch.text=Remove Watch
 action.XDebugger.RemoveAllWatches.text=Remove All Watches
 action.XDebugger.NewWatch.text=New Watch...
@@ -949,6 +953,7 @@
 action.Debugger.MarkObject.unmark.text=Unmark Object
 action.Debugger.MarkObject.description=Mark/unmark the object so that it can be visually distinguished in in debugger views
 action.Debugger.AddToWatch.text=Add to Watches
+action.Debugger.EvaluateInConsole.text=Evaluate in Console
 action.Debugger.AutoRenderer.text=Auto
 group.EditorPopupMenu.text=Editor Popup Menu
 group.EditorPopupMenu.description=Editor Popup Menu
diff --git a/platform/platform-resources-en/src/messages/DiffBundle.properties b/platform/platform-resources-en/src/messages/DiffBundle.properties
index 66a7bab..096fa11 100644
--- a/platform/platform-resources-en/src/messages/DiffBundle.properties
+++ b/platform/platform-resources-en/src/messages/DiffBundle.properties
@@ -32,7 +32,7 @@
 diff.acton.ignore.whitespace.policy.leading.and.trailing=Leading and trailing
 diff.acton.ignore.whitespace.policy.all=All
 ignore.whitespace.acton.name=Ignore whitespace:
-ignore.whitespace.action.not.available.action.name=<Not available>
+diff.panel.combo.box.action.not.available.action.name=<Not available>
 diff.dialog.select.change.action.name=Select Change
 diff.dialog.select.change.action.description=Select changed text in this version and corresponding in other
 merge.files.dialog.title=Merge
@@ -85,8 +85,7 @@
 diff.clipboard.vs.value.dialog.title=Clipboard vs Selected Value
 
 diff.can.not.show.unknown=Can not show diff for unknown file type
-diff.acton.highlight.mode.action.by.word=By Word
-diff.acton.highlight.mode.action.by.line=By Line
-diff.acton.highlight.mode.action.no.highlighting=No Highlighting
-diff.acton.highlight.mode.not.available.action.name=<Not available>
-diff.acton.highlight.mode.action.name=Highlighting Mode:
+diff.acton.highlight.mode.action.by.word=By word
+diff.acton.highlight.mode.action.by.line=By line
+diff.acton.highlight.mode.action.no.highlighting=Do not highlight
+diff.acton.highlight.mode.action.name=Highlight:
diff --git a/platform/platform-resources-en/src/messages/FindBundle.properties b/platform/platform-resources-en/src/messages/FindBundle.properties
index 26959ba..2c17b13 100644
--- a/platform/platform-resources-en/src/messages/FindBundle.properties
+++ b/platform/platform-resources-en/src/messages/FindBundle.properties
@@ -76,7 +76,7 @@
 find.filter.invalid.file.mask.error=Bad file mask \"{0}\"
 find.filter.empty.file.mask.error=Empty file mask
 find.options.case.sensitive=&Case sensitive
-find.options.replace.preserve.case=Preser&ve case
+find.options.replace.preserve.case=&Preserve case
 find.options.whole.words.only=Whole wo&rds only (may be faster)
 find.options.string.literals.only=S&tring literals only
 find.options.comments.only=Comm&ents only
@@ -85,7 +85,7 @@
 find.direction.forward.radio=F&orward
 find.direction.backward.radio=&Backward
 find.scope.group=Scope
-find.scope.whole.project.radio=Whole &project
+find.scope.whole.project.radio=W&hole project
 find.scope.all.projects.radio=All &projects
 find.scope.module.radio=&Module:
 find.scope.project.radio=Pro&ject
diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties
index b61965b..c156748 100644
--- a/platform/platform-resources-en/src/misc/registry.properties
+++ b/platform/platform-resources-en/src/misc/registry.properties
@@ -321,7 +321,6 @@
 
 comment.by.line.bulk.lines.trigger=100
 
-scene.builder.start.executable=true
 junit_sm_runner=false
 testng_sm_runner=false
 show.flex.debug.design.view=false
@@ -365,7 +364,7 @@
 ide.open.file.in.temp.project.dir.description=Enables opening file in temp project directory
 
 editor.allow.multiple.carets=false
-embed.scene.builder=false
+embed.scene.builder=true
 
 dsm.retina.darcula.legend=true
 dsm.retina.darcula.legend.description=Experimental DSM legend component
diff --git a/platform/platform-resources/src/DefaultColorSchemesManager.xml b/platform/platform-resources/src/DefaultColorSchemesManager.xml
index d43993b..b3f6d7f 100644
--- a/platform/platform-resources/src/DefaultColorSchemesManager.xml
+++ b/platform/platform-resources/src/DefaultColorSchemesManager.xml
@@ -416,20 +416,6 @@
           <option name="EFFECT_COLOR"/>
         </value>
       </option>
-      <option name="REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES">
-        <value>
-          <option name="FOREGROUND"/>
-          <option name="BACKGROUND"/>
-          <option name="EFFECT_COLOR"/>
-        </value>
-      </option>
-      <option name="REASSIGNED_PARAMETER_ATTRIBUTES">
-        <value>
-          <option name="FOREGROUND"/>
-          <option name="BACKGROUND"/>
-          <option name="EFFECT_COLOR"/>
-        </value>
-      </option>
       <option name="IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES">
         <value>
           <option name="FOREGROUND" value="660e7a"/>
diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml
index c554cf3..62fe042 100644
--- a/platform/platform-resources/src/META-INF/LangExtensions.xml
+++ b/platform/platform-resources/src/META-INF/LangExtensions.xml
@@ -343,6 +343,9 @@
     <projectService serviceInterface="com.intellij.openapi.roots.impl.LibraryScopeCache"
                     serviceImplementation="com.intellij.openapi.roots.impl.LibraryScopeCache"/>
 
+    <projectService serviceInterface="com.intellij.ide.scratch.ScratchpadManager"
+                    serviceImplementation="com.intellij.ide.scratch.ScratchpadManagerImpl"/>
+
     <colorSettingsPage implementation="com.intellij.openapi.options.colors.pages.GeneralColorsPage" id="general"/>
     <colorSettingsPage implementation="com.intellij.openapi.options.colors.pages.DefaultLanguageColorsPage" id="defaultLanguage"/>
     <colorSettingsPage implementation="com.intellij.openapi.options.colors.pages.ANSIColoredConsoleColorsPage" id="ansi"/>
@@ -875,6 +878,8 @@
     <stepsBeforeRunProvider implementation="com.intellij.execution.impl.RunConfigurationBeforeRunProvider"/>
 
     <lang.foldingBuilder language="TEXT" implementationClass="com.intellij.ide.highlighter.custom.impl.CustomFileTypeFoldingBuilder"/>
+
+    <virtualFileSystem key="scratchpad" implementationClass="com.intellij.ide.scratch.ScratchpadFileSystem"/>
   </extensions>
 </idea-plugin>
 
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
index 854e1ce..b6189cf 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
@@ -190,6 +190,8 @@
     <projectService serviceInterface="com.intellij.openapi.vcs.VcsFileListenerContextHelper"
                     serviceImplementation="com.intellij.openapi.vcs.VcsFileListenerContextHelper"/>
 
+    <projectService serviceImplementation="com.intellij.openapi.editor.LazyRangeMarkerFactory"/>
+
     <!-- General -->
     <applicationConfigurable instance="com.intellij.ide.GeneralSettingsConfigurable"/>
 
diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt
index e34b74e..a6d7603 100644
--- a/platform/platform-resources/src/brokenPlugins.txt
+++ b/platform/platform-resources/src/brokenPlugins.txt
@@ -9,7 +9,8 @@
 org.jetbrains.plugins.ruby 6.0.0.20140207
 Pythonid  3.1
 Karma    134.1163 134.1039 134.686  134.31
-org.intellij.scala    0.32.512
+org.intellij.scala 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512
 org.jetbrains.kannotator  0.2.420
 SBT   1.0.0  1.1.0  1.2.0  1.3.0  1.3.1  1.4.0  1.5.0
-"JSTestDriver Plugin"    134.1163 134.686 134.31 134.307 134.1039
\ No newline at end of file
+"JSTestDriver Plugin"    134.1163 134.686 134.31 134.307 134.1039
+AngularJS 134.1094 0.1.8 0.1.9
\ No newline at end of file
diff --git a/platform/platform-resources/src/componentSets/Editor.xml b/platform/platform-resources/src/componentSets/Editor.xml
index adf1f3b..25719ab 100644
--- a/platform/platform-resources/src/componentSets/Editor.xml
+++ b/platform/platform-resources/src/componentSets/Editor.xml
@@ -30,9 +30,5 @@
       <interface-class>com.intellij.openapi.fileEditor.ex.IdeDocumentHistory</interface-class>
       <implementation-class>com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl</implementation-class>
     </component>
-    <component>
-      <implementation-class>com.intellij.openapi.editor.LazyRangeMarkerFactory</implementation-class>
-      <loadForDefaultProject/>
-    </component>
   </project-components>
 </components>
\ No newline at end of file
diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml
index 447d4ab..c713584 100644
--- a/platform/platform-resources/src/idea/Keymap_Default.xml
+++ b/platform/platform-resources/src/idea/Keymap_Default.xml
@@ -115,7 +115,7 @@
   <action id="SelectNextOccurrence">
     <keyboard-shortcut first-keystroke="alt J"/>
   </action>
-  <action id="UnselectLastOccurrence">
+  <action id="UnselectPreviousOccurrence">
     <keyboard-shortcut first-keystroke="alt shift J"/>
   </action>
   <action id="GotoDeclaration">
@@ -958,5 +958,9 @@
   <action id ="Refactorings.QuickListPopupAction">
     <keyboard-shortcut first-keystroke="control alt shift T"/>
   </action>
+
+  <action id="NewScratchFile">
+    <keyboard-shortcut first-keystroke="control alt shift INSERT"/>
+  </action>
 </keymap>
 </component>
diff --git a/platform/platform-resources/src/idea/Keymap_Eclipse.xml b/platform/platform-resources/src/idea/Keymap_Eclipse.xml
index 2a28414..ecc3b04 100644
--- a/platform/platform-resources/src/idea/Keymap_Eclipse.xml
+++ b/platform/platform-resources/src/idea/Keymap_Eclipse.xml
@@ -121,10 +121,13 @@
     <action id="FindPrevious">
       <keyboard-shortcut first-keystroke="shift control K" />
     </action>
+    <action id="SelectAllOccurrences">
+      <keyboard-shortcut first-keystroke="alt control Y"/>
+    </action>
     <action id="SelectNextOccurrence">
       <keyboard-shortcut first-keystroke="alt Y"/>
     </action>
-    <action id="UnselectLastOccurrence">
+    <action id="UnselectPreviousOccurrence">
       <keyboard-shortcut first-keystroke="alt shift Y"/>
     </action>
     <action id="FindUsages">
diff --git a/platform/platform-resources/src/idea/Keymap_Mac.xml b/platform/platform-resources/src/idea/Keymap_Mac.xml
index 42cf466..32dd27f 100644
--- a/platform/platform-resources/src/idea/Keymap_Mac.xml
+++ b/platform/platform-resources/src/idea/Keymap_Mac.xml
@@ -349,6 +349,16 @@
     <action id="FindPrevious">
       <keyboard-shortcut first-keystroke="meta shift G"/>
     </action>
+    
+    <action id="SelectNextOccurrence">
+      <keyboard-shortcut first-keystroke="control G"/>
+    </action>
+    <action id="UnselectPreviousOccurrence">
+      <keyboard-shortcut first-keystroke="control shift G"/>
+    </action>
+    <action id="SelectAllOccurrences">
+      <keyboard-shortcut first-keystroke="meta control G"/>
+    </action>
 
     <action id="Run">
       <keyboard-shortcut first-keystroke="control R"/>
@@ -538,5 +548,9 @@
     <action id ="Refactorings.QuickListPopupAction">
       <keyboard-shortcut first-keystroke="control T"/>
     </action>
+
+    <action id="NewScratchFile">
+      <keyboard-shortcut first-keystroke="meta shift N"/>
+    </action>
   </keymap>
 </component>
diff --git a/platform/platform-resources/src/idea/Keymap_MacClassic.xml b/platform/platform-resources/src/idea/Keymap_MacClassic.xml
index 1ce8e72..532ac89 100644
--- a/platform/platform-resources/src/idea/Keymap_MacClassic.xml
+++ b/platform/platform-resources/src/idea/Keymap_MacClassic.xml
@@ -258,6 +258,16 @@
       <keyboard-shortcut first-keystroke="shift F3"/>
       <keyboard-shortcut first-keystroke="control shift L"/>
     </action>
+    
+    <action id="SelectNextOccurrence">
+      <keyboard-shortcut first-keystroke="control G"/>
+    </action>
+    <action id="UnselectPreviousOccurrence">
+      <keyboard-shortcut first-keystroke="control shift G"/>
+    </action>
+    <action id="SelectAllOccurrences">
+      <keyboard-shortcut first-keystroke="meta control G"/>
+    </action>
 
     <action id="VcsShowNextChangeMarker">
       <keyboard-shortcut first-keystroke="shift control alt DOWN"/>
diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml
index bdaf6c8..3b87982 100644
--- a/platform/platform-resources/src/idea/LangActions.xml
+++ b/platform/platform-resources/src/idea/LangActions.xml
@@ -319,6 +319,10 @@
       <add-to-group group-id="ToolsMenu" anchor="last"/>
     </group>
 
+    <action id="NewScratchFile" class="com.intellij.ide.scratch.CreateScratchFileAction">
+      <add-to-group group-id="ToolsBasicGroup" anchor="first"/>
+    </action>
+
     <group id="NewGroup" popup="true">
       <action id="NewFile" class="com.intellij.ide.actions.CreateFileAction"/>
       <action id="NewDir" class="com.intellij.ide.actions.CreateDirectoryOrPackageAction"/>
@@ -641,6 +645,7 @@
     </group>
 
     <action id="Debugger.AddToWatch" class="com.intellij.xdebugger.impl.actions.AddToWatchesAction" icon="AllIcons.Debugger.AddToWatch"/>
+    <action id="Debugger.EvaluateInConsole" class="com.intellij.xdebugger.impl.actions.EvaluateInConsoleAction"/>
 
     <group id="EditorPopupMenuDebug">
       <separator/>
@@ -648,6 +653,7 @@
       <reference ref="RunToCursor"/>
       <reference ref="ForceRunToCursor"/>
       <reference ref="Debugger.AddToWatch"/>
+      <reference ref="Debugger.EvaluateInConsole"/>
       <separator/>
 
       <add-to-group group-id="EditorLangPopupMenu" relative-to-action="EditorPopupMenu.Run" anchor="before"/>
@@ -662,7 +668,10 @@
       <action id="XDebugger.Inspect" class="com.intellij.xdebugger.impl.ui.tree.actions.XInspectAction"/>
       <action id="XDebugger.JumpToSource" class="com.intellij.xdebugger.impl.ui.tree.actions.XJumpToSourceAction"/>
       <action id="XDebugger.JumpToTypeSource" class="com.intellij.xdebugger.impl.ui.tree.actions.XJumpToTypeSourceAction"/>
-      <action id="XDebugger.AddToWatches" class="com.intellij.xdebugger.impl.ui.tree.actions.XAddToWatchesAction" icon="AllIcons.Debugger.AddToWatch"/>
+
+      <action id="Debugger.Tree.AddToWatches" class="com.intellij.xdebugger.impl.ui.tree.actions.XAddToWatchesAction" icon="AllIcons.Debugger.AddToWatch"/>
+      <action id="Debugger.Tree.EvaluateInConsole" class="com.intellij.xdebugger.impl.ui.tree.actions.EvaluateInConsoleFromTreeAction"/>
+
       <action id="XDebugger.NewWatch" class="com.intellij.xdebugger.impl.frame.actions.XNewWatchAction" icon="AllIcons.Debugger.NewWatch"/>
       <action id="XDebugger.EditWatch" class="com.intellij.xdebugger.impl.frame.actions.XEditWatchAction"/>
       <action id="XDebugger.RemoveWatch" class="com.intellij.xdebugger.impl.frame.actions.XRemoveWatchAction" icon="AllIcons.Actions.Delete"/>
@@ -712,7 +721,8 @@
       <reference ref="XDebugger.ValueGroup"/>
       <reference ref="XDebugger.JumpToSource"/>
       <reference ref="XDebugger.JumpToTypeSource"/>
-      <reference ref="XDebugger.AddToWatches"/>
+      <reference ref="Debugger.Tree.AddToWatches"/>
+      <reference ref="Debugger.Tree.EvaluateInConsole"/>
     </group>
 
     <group id="XDebugger.Variables.Tree.Toolbar">
@@ -733,7 +743,8 @@
 
     <group id="XDebugger.Inspect.Tree.Popup">
       <reference ref="XDebugger.ValueGroup"/>
-      <reference ref="XDebugger.AddToWatches"/>
+      <reference ref="Debugger.Tree.AddToWatches"/>
+      <reference ref="Debugger.Tree.EvaluateInConsole"/>
     </group>
 
     <group id="XDebugger.Settings" icon="AllIcons.General.SecondaryGroup" popup="true">
diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml
index e0e1360..5d2d399 100644
--- a/platform/platform-resources/src/idea/PlatformActions.xml
+++ b/platform/platform-resources/src/idea/PlatformActions.xml
@@ -225,8 +225,9 @@
           <action id="FindNext" class="com.intellij.ide.actions.SearchAgainAction"/>
           <action id="FindPrevious" class="com.intellij.ide.actions.SearchBackAction"/>
           <action id="FindWordAtCaret" class="com.intellij.openapi.editor.actions.FindWordAtCaretAction"/>
+          <action id="SelectAllOccurrences" class="com.intellij.openapi.editor.actions.SelectAllOccurrencesAction"/>
           <action id="SelectNextOccurrence" class="com.intellij.openapi.editor.actions.SelectNextOccurrenceAction"/>
-          <action id="UnselectLastOccurrence" class="com.intellij.openapi.editor.actions.UnselectLastOccurrenceAction"/>
+          <action id="UnselectPreviousOccurrence" class="com.intellij.openapi.editor.actions.UnselectPreviousOccurrenceAction"/>
           <separator/>
           <action id="FindInPath" class="com.intellij.find.actions.FindInPathAction"/>
           <action id="ReplaceInPath" class="com.intellij.find.actions.ReplaceInPathAction"/>
diff --git a/platform/platform-tests/platform-tests.iml b/platform/platform-tests/platform-tests.iml
index d101868..f6d37e4 100644
--- a/platform/platform-tests/platform-tests.iml
+++ b/platform/platform-tests/platform-tests.iml
@@ -23,6 +23,7 @@
     <orderEntry type="library" name="Groovy" level="project" />
     <orderEntry type="library" name="Netty" level="project" />
     <orderEntry type="library" name="http-client" level="project" />
+    <orderEntry type="module" module-name="jps-model-impl" scope="TEST" />
   </component>
 </module>
 
diff --git a/platform/platform-tests/testSrc/com/intellij/history/integration/TestVirtualFile.java b/platform/platform-tests/testSrc/com/intellij/history/integration/TestVirtualFile.java
index 9902918..44473df 100644
--- a/platform/platform-tests/testSrc/com/intellij/history/integration/TestVirtualFile.java
+++ b/platform/platform-tests/testSrc/com/intellij/history/integration/TestVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -33,12 +33,12 @@
 
 // todo get rid of!!!!!!!!!!!!!
 public class TestVirtualFile extends VirtualFile {
-  private String myName;
+  private final String myName;
   private String myContent;
   private boolean isReadOnly;
   private long myTimestamp;
 
-  private boolean IsDirectory;
+  private final boolean IsDirectory;
   private VirtualFile myParent;
   private final List<TestVirtualFile> myChildren = new ArrayList<TestVirtualFile>();
 
@@ -76,6 +76,7 @@
     return IsDirectory;
   }
 
+  @NotNull
   @Override
   public String getPath() {
     if (myParent == null) return myName;
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/IgnoreWhiteSpaceTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/IgnoreWhiteSpaceTest.java
index 7eb6c45..de5a6ba 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/IgnoreWhiteSpaceTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/IgnoreWhiteSpaceTest.java
@@ -31,4 +31,13 @@
     assertEquals(keys[1], keys[2]);
     assertFalse(keys[2].equals(keys[3]));
   }
+
+  public static void assertEquals(Object obj1, Object obj2) {
+    if (obj1 instanceof CharSequence && obj2 instanceof CharSequence) {
+      assertEquals(obj1.toString(), obj2.toString());
+      return;
+    }
+
+    assertEquals(obj1, obj2);
+  }
 }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/highlighting/UtilTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/highlighting/UtilTest.java
index db92920..1d19fb9 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/highlighting/UtilTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/highlighting/UtilTest.java
@@ -2,6 +2,7 @@
 
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.MultiCheck;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.util.Assertion;
 import com.intellij.util.diff.Diff;
 import com.intellij.util.diff.FilesTooBigForDiffException;
@@ -209,10 +210,11 @@
       last};
     lines = Util.uniteFormattingOnly(lines);
     CHECK.compareAll(new DiffFragment[][]{
-      first,
-      new DiffFragment[]{inline1, inline2, inline3, inline4},
-      last},
-                     lines);
+                       first,
+                       new DiffFragment[]{inline1, inline2, inline3, inline4},
+                       last},
+                     lines
+    );
   }
 
   public void testConcatenateEquals() {
@@ -246,7 +248,8 @@
     CHECK.singleElement(Util.cutFirst(new DiffFragment[]{
                           DiffFragment.unchanged("ab", "ac")
                         }),
-                        DiffFragment.unchanged("b", "c"));
+                        DiffFragment.unchanged("b", "c")
+    );
 
     CHECK.compareAll(new DiffFragment[]{
                        new DiffFragment(null, "c")
@@ -264,7 +267,8 @@
                      Util.cutFirst(new DiffFragment[]{
                        new DiffFragment(null, "ab"),
                        new DiffFragment("c", "d")
-                     }));
+                     })
+    );
   }
 
   public void testCutFirst2() {
@@ -293,4 +297,8 @@
                      }));
 
   }
+
+  public static void assertEquals(CharSequence obj1, CharSequence obj2) {
+    assertEquals(obj1.toString(), obj2.toString());
+  }
 }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/processing/LineBlocksDiffPolicyTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/processing/LineBlocksDiffPolicyTest.java
index badcc33..2baf119 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/processing/LineBlocksDiffPolicyTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/processing/LineBlocksDiffPolicyTest.java
@@ -5,7 +5,6 @@
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.highlighting.Util;
 import com.intellij.util.diff.FilesTooBigForDiffException;
-import junit.framework.Assert;
 import junit.framework.TestCase;
 
 public class LineBlocksDiffPolicyTest extends TestCase{
@@ -16,9 +15,9 @@
     checkPolicy(diffPolicy, "abc\n123\n", "ABC\nXYZ");
   }
 
-  private void checkPolicy(DiffPolicy.LineBlocks diffPolicy, String text1, String text2) throws FilesTooBigForDiffException {
+  private static void checkPolicy(DiffPolicy.LineBlocks diffPolicy, String text1, String text2) throws FilesTooBigForDiffException {
     DiffFragment[] fragments = diffPolicy.buildFragments(text1, text2);
-    Assert.assertEquals(text1, Util.getText(fragments, FragmentSide.SIDE1));
-    assertEquals(text2, Util.getText(fragments, FragmentSide.SIDE2));
+    assertEquals(text1, Util.getText(fragments, FragmentSide.SIDE1).toString());
+    assertEquals(text2, Util.getText(fragments, FragmentSide.SIDE2).toString());
   }
 }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/processing/TextCompareProcessorTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/processing/TextCompareProcessorTest.java
index 4d4ed9b..854a17d 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/processing/TextCompareProcessorTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/processing/TextCompareProcessorTest.java
@@ -5,12 +5,12 @@
 import com.intellij.util.diff.FilesTooBigForDiffException;
 import junit.framework.TestCase;
 
-import java.util.ArrayList;
+import java.util.List;
 
 public class TextCompareProcessorTest extends TestCase {
   public void testIgnoreWrappingEqualText() throws FilesTooBigForDiffException {
     TextCompareProcessor processor = new TextCompareProcessor(ComparisonPolicy.IGNORE_SPACE);
-    ArrayList<LineFragment> lineFragments = processor.process("f(a, b)\n", "f(a,\nb)\n");
+    List<LineFragment> lineFragments = processor.process("f(a, b)\n", "f(a,\nb)\n");
     assertTrue(lineFragments.size() == 1);
     assertNull(lineFragments.get(0).getType());
   }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretColumnModeTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretColumnModeTest.java
index 9b94c44..c4433cd 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretColumnModeTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretColumnModeTest.java
@@ -16,12 +16,12 @@
 package com.intellij.openapi.editor;
 
 import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.impl.AbstractEditorTest;
 import com.intellij.testFramework.EditorTestUtil;
-import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
 
 import java.io.IOException;
 
-public class EditorMultiCaretColumnModeTest extends LightPlatformCodeInsightTestCase {
+public class EditorMultiCaretColumnModeTest extends AbstractEditorTest {
   public void setUp() throws Exception {
     super.setUp();
     EditorTestUtil.enableMultipleCarets();
@@ -192,8 +192,99 @@
                       "bbbb bb<selection>bb<caret></selection>");
   }
 
+  public void testMoveToSelectionStart() throws Exception {
+    init("a");
+    mouse().clickAt(0, 2).dragTo(0, 4).release();
+    verifyCaretsAndSelections(0, 4, 0, 2, 0, 4);
+
+    executeAction("EditorLeft");
+    verifyCaretsAndSelections(0, 2, 0, 2, 0, 2);
+  }
+
+  public void testMoveToSelectionEnd() throws Exception {
+    init("a");
+    mouse().clickAt(0, 4).dragTo(0, 2).release();
+    verifyCaretsAndSelections(0, 2, 0, 2, 0, 4);
+
+    executeAction("EditorRight");
+    verifyCaretsAndSelections(0, 4, 0, 4, 0, 4);
+  }
+
+  public void testReverseBlockSelection() throws Exception {
+    init("a");
+    mouse().clickAt(0, 4).dragTo(0, 3).release();
+    verifyCaretsAndSelections(0, 3, 0, 3, 0, 4);
+
+    executeAction("EditorRightWithSelection");
+    verifyCaretsAndSelections(0, 4, 0, 4, 0, 4);
+  }
+
+  public void testSelectionWithKeyboardInEmptySpace() throws Exception {
+    init("\n\n");
+    mouse().clickAt(1, 1);
+    verifyCaretsAndSelections(1, 1, 1, 1, 1, 1);
+
+    executeAction("EditorRightWithSelection");
+    verifyCaretsAndSelections(1, 2, 1, 1, 1, 2);
+
+    executeAction("EditorDownWithSelection");
+    verifyCaretsAndSelections(1, 2, 1, 1, 1, 2,
+                              2, 2, 2, 1, 2, 2);
+
+    executeAction("EditorLeftWithSelection");
+    verifyCaretsAndSelections(1, 1, 1, 1, 1, 1,
+                              2, 1, 2, 1, 2, 1);
+
+    executeAction("EditorLeftWithSelection");
+    verifyCaretsAndSelections(1, 0, 1, 0, 1, 1,
+                              2, 0, 2, 0, 2, 1);
+
+    executeAction("EditorUpWithSelection");
+    verifyCaretsAndSelections(1, 0, 1, 0, 1, 1);
+
+    executeAction("EditorUpWithSelection");
+    verifyCaretsAndSelections(0, 0, 0, 0, 0, 1,
+                              1, 0, 1, 0, 1, 1);
+
+    executeAction("EditorRightWithSelection");
+    verifyCaretsAndSelections(0, 1, 0, 1, 0, 1,
+                              1, 1, 1, 1, 1, 1);
+
+    executeAction("EditorRightWithSelection");
+    verifyCaretsAndSelections(0, 2, 0, 1, 0, 2,
+                              1, 2, 1, 1, 1, 2);
+
+    executeAction("EditorDownWithSelection");
+    verifyCaretsAndSelections(1, 2, 1, 1, 1, 2);
+
+    executeAction("EditorLeftWithSelection");
+    verifyCaretsAndSelections(1, 1, 1, 1, 1, 1);
+  }
+
+  public void testBlockSelection() throws Exception {
+    init("a\n" +
+         "bbb\n" +
+         "ccccc");
+    mouse().clickAt(2, 4).dragTo(0, 1).release();
+    verifyCaretsAndSelections(0, 1, 0, 1, 0, 4,
+                              1, 1, 1, 1, 1, 4,
+                              2, 1, 2, 1, 2, 4);
+  }
+
+  public void testTyping() throws Exception {
+    init("a\n" +
+         "bbb\n" +
+         "ccccc");
+    mouse().clickAt(0, 2).dragTo(2, 3).release();
+    type('S');
+    checkResultByText("a S<caret>\n" +
+                      "bbS<caret>\n" +
+                      "ccS<caret>cc");
+  }
+
   private void init(String text) throws IOException {
     configureFromFileText(getTestName(false) + ".txt", text);
+    EditorTestUtil.setEditorVisibleSize(myEditor, 1000, 1000);
     ((EditorEx)myEditor).setColumnMode(true);
   }
 }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretUndoRedoTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretUndoRedoTest.java
index 0b168c4..6f13af4 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretUndoRedoTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretUndoRedoTest.java
@@ -21,6 +21,7 @@
 import com.intellij.openapi.command.impl.CurrentEditorProvider;
 import com.intellij.openapi.command.impl.UndoManagerImpl;
 import com.intellij.openapi.command.undo.UndoManager;
+import com.intellij.openapi.editor.ex.EditorEx;
 import com.intellij.openapi.editor.impl.AbstractEditorTest;
 import com.intellij.openapi.fileEditor.FileEditor;
 import com.intellij.openapi.fileEditor.TextEditor;
@@ -29,6 +30,8 @@
 import com.intellij.testFramework.TestFileType;
 import org.jetbrains.annotations.NotNull;
 
+import java.io.IOException;
+
 public class EditorMultiCaretUndoRedoTest extends AbstractEditorTest {
   private CurrentEditorProvider mySavedCurrentEditorProvider;
 
@@ -58,9 +61,7 @@
   public void testUndoRedo() throws Exception {
     init("some<caret> text<caret>\n" +
          "some <selection><caret>other</selection> <selection>text<caret></selection>\n" +
-         "<selection>ano<caret>ther</selection> line",
-         TestFileType.TEXT);
-    setupEditorProvider();
+         "<selection>ano<caret>ther</selection> line");
     type('A');
     executeAction("EditorDelete");
     mouse().clickAt(0, 1);
@@ -80,6 +81,25 @@
                       "A<caret> line");
   }
 
+  public void testBlockSelectionStateAfterUndo() throws Exception {
+    init("a");
+    ((EditorEx)myEditor).setColumnMode(true);
+    mouse().clickAt(0, 2);
+    type('b');
+    undo();
+    executeAction("EditorRightWithSelection");
+    verifyCaretsAndSelections(0, 3, 0, 2, 0, 3);
+  }
+
+  public void testBlockSelectionStateAfterUndo2() throws Exception {
+    init("a");
+    ((EditorEx)myEditor).setColumnMode(true);
+    mouse().clickAt(0, 0).dragTo(0, 2).release();
+    type('b');
+    undo();
+    verifyCaretsAndSelections(0, 2, 0, 0, 0, 2);
+  }
+
   private void checkResult(final String text) {
     CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
       @Override
@@ -105,7 +125,9 @@
     return TextEditorProvider.getInstance().getTextEditor(myEditor);
   }
 
-  private static void setupEditorProvider() {
+  private void init(String text) throws IOException {
+    init(text, TestFileType.TEXT);
+    EditorTestUtil.setEditorVisibleSize(myEditor, 1000, 1000);
     getUndoManager().setEditorProvider(new CurrentEditorProvider() {
       @Override
       public FileEditor getCurrentEditor() {
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectUnselectOccurrenceActionsTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectUnselectOccurrenceActionsTest.java
index 90a82e9..42faeaa 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectUnselectOccurrenceActionsTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectUnselectOccurrenceActionsTest.java
@@ -49,6 +49,30 @@
     super.tearDown();
   }
 
+  public void testAllWithoutInitialSelection() throws Exception {
+    init("some t<caret>ext\n" +
+         "some texts\n" +
+         "another text here"
+    );
+    executeSelectAllAction();
+    checkResult("some <selection>t<caret>ext</selection>\n" +
+                "some texts\n" +
+                "another <selection>t<caret>ext</selection> here");
+  }
+
+  public void testAllWithInitialWholeWordSelection() throws Exception {
+    init("some <selection>t<caret>ext</selection>\n" +
+         "some texts\n" +
+         "some texts\n" +
+         "another text here");
+    executeSelectAllAction();
+    checkResult("some <selection>t<caret>ext</selection>\n" +
+                "some texts\n" +
+                "some texts\n" +
+                "another <selection>t<caret>ext</selection> here");
+    assertEquals(0, hintCount);
+  }
+
   public void testNoInitialSelection() throws Exception {
     init("some t<caret>ext\n" +
          "some texts\n" +
@@ -182,6 +206,10 @@
   }
 
   private void executeReverseAction() {
-    myFixture.performEditorAction(IdeActions.ACTION_UNSELECT_LAST_OCCURENCE);
+    myFixture.performEditorAction(IdeActions.ACTION_UNSELECT_PREVIOUS_OCCURENCE);
+  }
+
+  private void executeSelectAllAction() {
+    myFixture.performEditorAction(IdeActions.ACTION_SELECT_ALL_OCCURRENCES);
   }
 }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
index bbb8de3..2c460a5 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
@@ -15,9 +15,7 @@
  */
 package com.intellij.openapi.editor.impl;
 
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.FoldRegion;
-import com.intellij.openapi.editor.FoldingModel;
+import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.ex.FoldingModelEx;
 import com.intellij.openapi.editor.impl.softwrap.mapping.CachingSoftWrapDataMapper;
 import com.intellij.openapi.util.Pair;
@@ -220,4 +218,18 @@
   public EditorMouseFixture mouse() {
     return new EditorMouseFixture((EditorImpl)myEditor);
   }
+
+  // for each caret its visual position and visual positions of selection start an and should be provided in the following order:
+  // caretLine, caretColumn, selectionStartLine, selectionStartColumn, selectionEndLine, selectionEndColumn
+  public static void verifyCaretsAndSelections(int... coordinates) {
+    int caretCount = coordinates.length / 6;
+    List<Caret> carets = myEditor.getCaretModel().getAllCarets();
+    assertEquals("Unexpected caret count", caretCount, carets.size());
+    for (int i = 0; i < caretCount; i++) {
+      Caret caret = carets.get(i);
+      assertEquals("Unexpected position for caret " + (i + 1), new VisualPosition(coordinates[i * 6], coordinates[i * 6 + 1]), caret.getVisualPosition());
+      assertEquals("Unexpected selection start for caret " + (i + 1), new VisualPosition(coordinates[i * 6 + 2], coordinates[i * 6 + 3]), caret.getSelectionStartPosition());
+      assertEquals("Unexpected selection end for caret " + (i + 1), new VisualPosition(coordinates[i * 6 + 4], coordinates[i * 6 + 5]), caret.getSelectionEndPosition());
+    }
+  }
 }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java
index 2b8f99e..2502e76 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java
@@ -15,21 +15,42 @@
  */
 package com.intellij.openapi.editor.impl;
 
+import com.intellij.openapi.editor.colors.EditorColors;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.ex.EditorEx;
 import com.intellij.openapi.fileTypes.PlainTextFileType;
 import com.intellij.testFramework.EditorTestUtil;
+import com.intellij.testFramework.fixtures.EditorMouseFixture;
 import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
-import org.jetbrains.annotations.NotNull;
 import org.junit.Assert;
 
 import java.awt.*;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 
 public class IterationStateTest extends LightPlatformCodeInsightFixtureTestCase {
 
+  private Color DEFAULT_BACKGROUND;
+  private Color CARET_ROW_BACKGROUND;
+  private Color SELECTION_BACKGROUND;
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    EditorColorsScheme colorsScheme = EditorColorsManager.getInstance().getGlobalScheme();
+    DEFAULT_BACKGROUND = colorsScheme.getDefaultBackground();
+    CARET_ROW_BACKGROUND = colorsScheme.getColor(EditorColors.CARET_ROW_COLOR);
+    SELECTION_BACKGROUND = colorsScheme.getColor(EditorColors.SELECTION_BACKGROUND_COLOR);
+    assertEquals(3, new HashSet<Color>(Arrays.asList(DEFAULT_BACKGROUND, CARET_ROW_BACKGROUND, SELECTION_BACKGROUND)).size());
+  }
+
   public void testBlockSelection() {
-    verifySplitting("aa,<block>bb\ncc,d</block>d",
+    init("aa,<block>bb\n" +
+         "cc,d</block>d");
+    verifySplitting(true,
                     new Segment(0, 3, Color.BLACK),
                     new Segment(3, 4, Color.WHITE),
                     new Segment(4, 5, Color.BLACK),
@@ -49,20 +70,106 @@
     }
   }
 
-  private void verifySplitting(String text, Segment... expectedSegments) {
-    myFixture.configureByText(PlainTextFileType.INSTANCE, text);
+  public void testColumnModeBlockSelection() {
+    EditorTestUtil.enableMultipleCarets();
+    try {
+      init("a\n" +
+           "bbb\n" +
+           "ccccc");
+      setColumnModeOn();
+      mouse().clickAt(0, 2).dragTo(2, 4).release();
+      verifySplitting(false,
+                      new Segment(0, 1, DEFAULT_BACKGROUND),
+                      new Segment(1, 2, DEFAULT_BACKGROUND).plus(1, DEFAULT_BACKGROUND).plus(2, SELECTION_BACKGROUND),
+                      new Segment(2, 4, DEFAULT_BACKGROUND),
+                      new Segment(4, 5, SELECTION_BACKGROUND),
+                      new Segment(5, 6, DEFAULT_BACKGROUND).plus(1, SELECTION_BACKGROUND),
+                      new Segment(6, 8, CARET_ROW_BACKGROUND),
+                      new Segment(8, 10, SELECTION_BACKGROUND),
+                      new Segment(10, 11, CARET_ROW_BACKGROUND));
+    }
+    finally {
+      EditorTestUtil.disableMultipleCarets();
+    }
+  }
+
+  public void testColumnModeBlockSelectionAtLastNonEmptyLine() {
+    EditorTestUtil.enableMultipleCarets();
+    try {
+      init("a\n" +
+           "bbb\n" +
+           "ccccc");
+      setColumnModeOn();
+      mouse().clickAt(0, 2).dragTo(2, 6).release();
+      verifySplitting(false,
+                      new Segment(0, 1, DEFAULT_BACKGROUND),
+                      new Segment(1, 2, DEFAULT_BACKGROUND).plus(1, DEFAULT_BACKGROUND).plus(4, SELECTION_BACKGROUND),
+                      new Segment(2, 4, DEFAULT_BACKGROUND),
+                      new Segment(4, 5, SELECTION_BACKGROUND),
+                      new Segment(5, 6, DEFAULT_BACKGROUND).plus(3, SELECTION_BACKGROUND),
+                      new Segment(6, 8, CARET_ROW_BACKGROUND),
+                      new Segment(8, 11, SELECTION_BACKGROUND),
+                      new Segment(11, 11, null).plus(1, SELECTION_BACKGROUND));
+    }
+    finally {
+      EditorTestUtil.disableMultipleCarets();
+    }
+  }
+
+  public void testColumnModeBlockSelectionAtLastEmptyLine() {
+    EditorTestUtil.enableMultipleCarets();
+    try {
+      init("a\n" +
+           "");
+      setColumnModeOn();
+      mouse().clickAt(1, 1).dragTo(1, 2).release();
+      verifySplitting(false,
+                      new Segment(0, 1, DEFAULT_BACKGROUND),
+                      new Segment(1, 2, DEFAULT_BACKGROUND),
+                      new Segment(2, 2, null).plus(1, CARET_ROW_BACKGROUND).plus(1, SELECTION_BACKGROUND));
+    }
+    finally {
+      EditorTestUtil.disableMultipleCarets();
+    }
+  }
+
+  public void testColumnModeBlockSelectionAtEmptyLines() {
+    EditorTestUtil.enableMultipleCarets();
+    try {
+      init("\n");
+      setColumnModeOn();
+      mouse().clickAt(0, 1).dragTo(1, 2).release();
+      verifySplitting(false,
+                      new Segment(0, 1, DEFAULT_BACKGROUND).plus(1, DEFAULT_BACKGROUND).plus(1, SELECTION_BACKGROUND),
+                      new Segment(1, 1, null).plus(1, CARET_ROW_BACKGROUND).plus(1, SELECTION_BACKGROUND));
+    }
+    finally {
+      EditorTestUtil.disableMultipleCarets();
+    }
+  }
+
+  private void verifySplitting(boolean checkForegroundColor, Segment... expectedSegments) {
     EditorEx editor = (EditorEx)myFixture.getEditor();
     IterationState iterationState = new IterationState(editor, 0, editor.getDocument().getTextLength(), true);
     try {
       List<Segment> actualSegments = new ArrayList<Segment>();
       do {
-        actualSegments.add(new Segment(iterationState.getStartOffset(),
-                                       iterationState.getEndOffset(),
-                                       iterationState.getMergedAttributes().getForegroundColor()));
+        Segment segment = new Segment(iterationState.getStartOffset(),
+                                      iterationState.getEndOffset(),
+                                      checkForegroundColor ? iterationState.getMergedAttributes().getForegroundColor()
+                                                           : iterationState.getMergedAttributes().getBackgroundColor());
+        readPastLineState(iterationState, segment);
+        actualSegments.add(segment);
         iterationState.advance();
       }
       while (!iterationState.atEnd());
 
+      if (iterationState.hasPastFileEndBackgroundSegments()) {
+        Segment segment = new Segment(iterationState.getEndOffset(), iterationState.getEndOffset(), null);
+        readPastLineState(iterationState, segment);
+        actualSegments.add(segment);
+      }
+
       Assert.assertArrayEquals(expectedSegments, actualSegments.toArray());
     }
     finally {
@@ -70,15 +177,46 @@
     }
   }
 
+  private static void readPastLineState(IterationState iterationState, Segment segment) {
+    while(iterationState.hasPastLineEndBackgroundSegment()) {
+      segment.plus(iterationState.getPastLineEndBackgroundSegmentWidth(), iterationState.getPastLineEndBackgroundAttributes().getBackgroundColor());
+      iterationState.advanceToNextPastLineEndBackgroundSegment();
+    }
+  }
+
+  private void init(String text) {
+    myFixture.configureByText(PlainTextFileType.INSTANCE, text);
+    EditorTestUtil.setEditorVisibleSize(myFixture.getEditor(), 1000, 1000);
+  }
+
+  private void setColumnModeOn() {
+    ((EditorEx)myFixture.getEditor()).setColumnMode(true);
+  }
+
+  private EditorMouseFixture mouse() {
+    return new EditorMouseFixture((EditorImpl)myFixture.getEditor());
+  }
+
   private static class Segment {
     private final int start;
     private final int end;
-    private final Color fgColor;
+    private final Color color;
+    private final List<Integer> pastLineEndSegmentWidths = new ArrayList<Integer>();
+    private final List<Color> pastLineEndSegmentColors = new ArrayList<Color>();
 
-    private Segment(int start, int end, @NotNull Color fgColor) {
+    private Segment(int start, int end, Color color) {
       this.start = start;
       this.end = end;
-      this.fgColor = fgColor;
+      this.color = color;
+    }
+
+    /**
+     * Adds a past-line-end background segment
+     */
+    private Segment plus(int width, Color color) {
+      pastLineEndSegmentWidths.add(width);
+      pastLineEndSegmentColors.add(color);
+      return this;
     }
 
     @Override
@@ -90,7 +228,9 @@
 
       if (end != segment.end) return false;
       if (start != segment.start) return false;
-      if (!fgColor.equals(segment.fgColor)) return false;
+      if (color != null ? !color.equals(segment.color) : segment.color != null) return false;
+      if (!pastLineEndSegmentColors.equals(segment.pastLineEndSegmentColors)) return false;
+      if (!pastLineEndSegmentWidths.equals(segment.pastLineEndSegmentWidths)) return false;
 
       return true;
     }
@@ -99,7 +239,9 @@
     public int hashCode() {
       int result = start;
       result = 31 * result + end;
-      result = 31 * result + fgColor.hashCode();
+      result = 31 * result + (color != null ? color.hashCode() : 0);
+      result = 31 * result + pastLineEndSegmentWidths.hashCode();
+      result = 31 * result + pastLineEndSegmentColors.hashCode();
       return result;
     }
 
@@ -108,7 +250,9 @@
       return "Segment{" +
              "start=" + start +
              ", end=" + end +
-             ", color=" + fgColor +
+             ", color=" + color +
+             (pastLineEndSegmentWidths.isEmpty() ? "" : ", pastLineEndSegmentWidths=" + pastLineEndSegmentWidths) +
+             (pastLineEndSegmentColors.isEmpty() ? "" : ", pastLineEndSegmentColors=" + pastLineEndSegmentColors) +
              '}';
     }
   }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java
index cf53f97..09debec 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTest.java
@@ -17,29 +17,20 @@
 
 import com.intellij.ide.ui.UISettings;
 import com.intellij.mock.Mock;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.components.ExpandMacroToPathMap;
 import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.JDOMUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.testFramework.PlatformTestCase;
 import com.intellij.testFramework.PlatformTestUtil;
 import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
-import org.jdom.Document;
 import org.jdom.Element;
-import org.jdom.JDOMException;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jps.model.serialization.PathMacroUtil;
 
 import javax.swing.*;
 import java.io.File;
-import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 
 /**
  * @author Dmitry Avdeev
@@ -77,17 +68,18 @@
 
     openFiles("  <component name=\"FileEditorManager\">\n" +
         "    <leaf>\n" +
-        "      <file leaf-file-name=\"foo.xsd\" pinned=\"false\" current=\"true\" current-in-tab=\"true\">\n" +
-        "        <entry selected=\"true\" file=\"file://$PROJECT_DIR$/src/1.txt\">\n" +
-        "          <provider editor-type-id=\"mock\" selected=\"true\">\n" +
-        "            <state />\n" +
-        "          </provider>\n" +
-        "          <provider editor-type-id=\"text-editor\">\n" +
-        "            <state/>\n" +
+        "      <file leaf-file-name=\"Bar.java\" pinned=\"false\" current=\"false\" current-in-tab=\"false\">\n" +
+        "        <entry file=\"file://$PROJECT_DIR$/src/Bar.java\">\n" +
+        "          <provider selected=\"true\" editor-type-id=\"text-editor\">\n" +
+        "            <state vertical-scroll-proportion=\"0.0\" vertical-offset=\"0\" max-vertical-offset=\"187\">\n" +
+        "              <caret line=\"1\" column=\"26\" selection-start=\"45\" selection-end=\"45\" />\n" +
+        "              <folding>\n" +
+        "                <element signature=\"e#69#70#0\" expanded=\"true\" />\n" +
+        "              </folding>\n" +
+        "            </state>\n" +
         "          </provider>\n" +
         "        </entry>\n" +
         "      </file>\n" +
-        "    </leaf>\n" +
         "  </component>\n");
     FileEditor[] selectedEditors = myManager.getSelectedEditors();
     assertEquals(1, selectedEditors.length);
@@ -157,24 +149,6 @@
     assertEquals(Arrays.asList(fileNames), names);
   }
 
-  private void openFiles(String s) throws IOException, JDOMException, InterruptedException, ExecutionException {
-    Document document = JDOMUtil.loadDocument(s);
-    Element rootElement = document.getRootElement();
-    ExpandMacroToPathMap map = new ExpandMacroToPathMap();
-    map.addMacroExpand(PathMacroUtil.PROJECT_DIR_MACRO_NAME, getTestDataPath());
-    map.substitute(rootElement, true, true);
-
-    myManager.readExternal(rootElement);
-
-    Future<?> future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
-      @Override
-      public void run() {
-        myManager.getMainSplitters().openFiles();
-      }
-    });
-    future.get();
-  }
-
   @Override
   protected String getTestDataPath() {
     return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/platform/platform-tests/testData/fileEditorManager";
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTestCase.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTestCase.java
index aa52868..28d5def 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTestCase.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileEditorManagerTestCase.java
@@ -1,13 +1,27 @@
 package com.intellij.openapi.fileEditor;
 
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.ExpandMacroToPathMap;
 import com.intellij.openapi.components.impl.ComponentManagerImpl;
 import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager;
 import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
 import com.intellij.openapi.fileEditor.impl.FileEditorProviderManagerImpl;
+import com.intellij.openapi.util.JDOMUtil;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
 import com.intellij.ui.docking.DockManager;
+import com.intellij.util.ui.UIUtil;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jetbrains.jps.model.serialization.PathMacroUtil;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 /**
  * @author Dmitry Avdeev
@@ -40,4 +54,30 @@
   protected VirtualFile getFile(String path) {
     return LocalFileSystem.getInstance().refreshAndFindFileByPath(getTestDataPath() + path);
   }
+
+  protected void openFiles(String s) throws IOException, JDOMException, InterruptedException, ExecutionException {
+    Document document = JDOMUtil.loadDocument(s);
+    Element rootElement = document.getRootElement();
+    ExpandMacroToPathMap map = new ExpandMacroToPathMap();
+    map.addMacroExpand(PathMacroUtil.PROJECT_DIR_MACRO_NAME, getTestDataPath());
+    map.substitute(rootElement, true, true);
+
+    myManager.readExternal(rootElement);
+
+    Future<?> future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+      @Override
+      public void run() {
+        myManager.getMainSplitters().openFiles();
+      }
+    });
+    while (true) {
+      try {
+        future.get(100, TimeUnit.MILLISECONDS);
+        return;
+      }
+      catch (TimeoutException e) {
+        UIUtil.dispatchAllInvocationEvents();
+      }
+    }
+  }
 }
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/EnforcedPlaintTextFileTypeManagerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/EnforcedPlaintTextFileTypeManagerTest.java
new file mode 100644
index 0000000..2fe2787
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/EnforcedPlaintTextFileTypeManagerTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.fileTypes;
+
+import com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeFactory;
+import com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+
+/**
+ * @author Rustam Vishnyakov
+ */
+public class EnforcedPlaintTextFileTypeManagerTest extends LightPlatformCodeInsightFixtureTestCase {
+  public void testMarkAsPlainText() {
+    EnforcedPlainTextFileTypeManager manager = EnforcedPlainTextFileTypeManager.getInstance();
+    VirtualFile file = myFixture.getTempDirFixture().createFile("test.java");
+    FileType originalType = file.getFileType();
+    assertEquals("JAVA", originalType.getName());
+    manager.markAsPlainText(file);
+    FileType changedType = file.getFileType();
+    assertEquals(EnforcedPlainTextFileTypeFactory.ENFORCED_PLAIN_TEXT, changedType.getName());
+    manager.resetOriginalFileType(file);
+    FileType revertedType = file.getFileType();
+    assertEquals(originalType, revertedType);
+  }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/remotesdk/RemoteFileTest.java b/platform/platform-tests/testSrc/com/intellij/remotesdk/RemoteFileTest.java
index d53ae4a..7133c98 100644
--- a/platform/platform-tests/testSrc/com/intellij/remotesdk/RemoteFileTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/remotesdk/RemoteFileTest.java
@@ -15,6 +15,8 @@
  */
 package com.intellij.remotesdk;
 
+import com.intellij.remote.RemoteFile;
+import com.intellij.remote.RemoteSdkCredentialsHolder;
 import junit.framework.TestCase;
 
 /**
diff --git a/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapTest.java b/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapTest.java
index f40716b..7a41730 100644
--- a/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapTest.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.util.io;
 
 import com.intellij.openapi.util.io.FileUtil;
@@ -8,6 +23,7 @@
 import com.intellij.util.io.storage.AbstractStorage;
 import gnu.trove.THashSet;
 import junit.framework.TestCase;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 import java.util.*;
@@ -424,13 +440,13 @@
     FileUtil.createParentDirs(file);
     EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor();
     class PathCollectionExternalizer implements DataExternalizer<Collection<String>> {
-      public void save(DataOutput out, Collection<String> value) throws IOException {
+      public void save(@NotNull DataOutput out, Collection<String> value) throws IOException {
         for (String str : value) {
           IOUtil.writeString(str, out);
         }
       }
 
-      public Collection<String> read(DataInput in) throws IOException {
+      public Collection<String> read(@NotNull DataInput in) throws IOException {
         final Set<String> result = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
         final DataInputStream stream = (DataInputStream)in;
         while (stream.available() > 0) {
diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectRootManager.java b/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectRootManager.java
index 8d1ef81..c0ed5c0 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectRootManager.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectRootManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@
    * @param project the project for which the instance is requested.
    * @return the instance.
    */
-  public static ProjectRootManager getInstance(Project project) {
+  public static ProjectRootManager getInstance(@NotNull Project project) {
     final ProjectRootManager service = ServiceManager.getService(project, ProjectRootManager.class);
     if (service != null) return service;
     return project.getComponent(ProjectRootManager.class);
diff --git a/platform/projectModel-impl/src/com/intellij/core/CoreModule.java b/platform/projectModel-impl/src/com/intellij/core/CoreModule.java
index 86fbdf7..fc4f2de 100644
--- a/platform/projectModel-impl/src/com/intellij/core/CoreModule.java
+++ b/platform/projectModel-impl/src/com/intellij/core/CoreModule.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -177,51 +177,61 @@
     throw new UnsupportedOperationException();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleScope() {
     return myModuleScopeProvider.getModuleScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleScope(boolean includeTests) {
     return myModuleScopeProvider.getModuleScope(includeTests);
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithLibrariesScope() {
     return myModuleScopeProvider.getModuleWithLibrariesScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependenciesScope() {
     return myModuleScopeProvider.getModuleWithDependenciesScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleContentScope() {
     return myModuleScopeProvider.getModuleContentScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleContentWithDependenciesScope() {
     return myModuleScopeProvider.getModuleContentWithDependenciesScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependenciesAndLibrariesScope(boolean includeTests) {
     return myModuleScopeProvider.getModuleWithDependenciesAndLibrariesScope(includeTests);
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependentsScope() {
     return myModuleScopeProvider.getModuleWithDependentsScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleTestsWithDependentsScope() {
     return myModuleScopeProvider.getModuleTestsWithDependentsScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleRuntimeScope(boolean includeTests) {
     return myModuleScopeProvider.getModuleRuntimeScope(includeTests);
diff --git a/platform/projectModel-impl/src/com/intellij/core/CoreModuleScopeProvider.java b/platform/projectModel-impl/src/com/intellij/core/CoreModuleScopeProvider.java
index aeafc19..1473232 100644
--- a/platform/projectModel-impl/src/com/intellij/core/CoreModuleScopeProvider.java
+++ b/platform/projectModel-impl/src/com/intellij/core/CoreModuleScopeProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 
 import com.intellij.openapi.module.impl.ModuleScopeProvider;
 import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Author: dmitrylomov
@@ -25,51 +26,61 @@
   public CoreModuleScopeProvider() {
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleScope() {
     throw new UnsupportedOperationException();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleScope(boolean includeTests) {
     throw new UnsupportedOperationException();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithLibrariesScope() {
     throw new UnsupportedOperationException();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependenciesScope() {
     throw new UnsupportedOperationException();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleContentScope() {
     throw new UnsupportedOperationException();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleContentWithDependenciesScope() {
     throw new UnsupportedOperationException();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependenciesAndLibrariesScope(boolean includeTests) {
     throw new UnsupportedOperationException();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependentsScope() {
     throw new UnsupportedOperationException();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleTestsWithDependentsScope() {
     throw new UnsupportedOperationException();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleRuntimeScope(boolean includeTests) {
     throw new UnsupportedOperationException();
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java
index 6041f61..9cabfb6 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.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.
@@ -477,10 +477,7 @@
 
   @Override
   @NotNull
-  public Module loadModule(@NotNull String filePath) throws InvalidDataException,
-                                                   IOException,
-                                                   JDOMException,
-                                                   ModuleWithNameAlreadyExists {
+  public Module loadModule(@NotNull String filePath) throws InvalidDataException, IOException, JDOMException, ModuleWithNameAlreadyExists {
     myModificationCount++;
     final ModifiableModuleModel modifiableModel = getModifiableModel();
     final Module module = modifiableModel.loadModule(filePath);
@@ -745,10 +742,9 @@
       }
     }
 
-    private Module loadModuleInternal(String filePath)
-      throws ModuleWithNameAlreadyExists, IOException, StateStorageException {
-
-      final VirtualFile moduleFile = StandardFileSystems.local().findFileByPath(resolveShortWindowsName(filePath));
+    private Module loadModuleInternal(String filePath) throws ModuleWithNameAlreadyExists, IOException, StateStorageException {
+      filePath = resolveShortWindowsName(filePath);
+      final VirtualFile moduleFile = StandardFileSystems.local().findFileByPath(filePath);
       if (moduleFile == null || !moduleFile.exists()) {
         throw new IOException(ProjectBundle.message("module.file.does.not.exist.error", filePath));
       }
diff --git a/platform/remote-servers/impl/resources/resources/cloud.properties b/platform/remote-servers/impl/resources/resources/cloud.properties
index f763799..24aae89 100644
--- a/platform/remote-servers/impl/resources/resources/cloud.properties
+++ b/platform/remote-servers/impl/resources/resources/cloud.properties
@@ -5,4 +5,4 @@
 failed.reset.remote=Failed to set {0} repository as remote
 cloning.existing.application=Cloning existing {0} application
 fetching.application=Fetching {0} application
-
+run.configuration.name={0} - {1}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.form b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.form
new file mode 100644
index 0000000..bbfd6da
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.form
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.remoteServer.util.CloudAccountSelectionEditor">
+  <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="82588" class="javax.swing.JComboBox" binding="myServerComboBox">
+        <constraints>
+          <grid row="0" column="0" 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>
+      <grid id="27f9c" binding="myServerConfigurablePanel" custom-create="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="0" left="0" bottom="0" right="0"/>
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children/>
+      </grid>
+      <vspacer id="dcc88">
+        <constraints>
+          <grid row="2" 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>
+    </children>
+  </grid>
+</form>
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java
new file mode 100644
index 0000000..aab46e7
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.remoteServer.util;
+
+import com.intellij.execution.RunManagerEx;
+import com.intellij.execution.RunnerAndConfigurationSettings;
+import com.intellij.execution.configurations.ConfigurationType;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModulePointer;
+import com.intellij.openapi.module.ModulePointerManager;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.RemoteServersManager;
+import com.intellij.remoteServer.impl.configuration.RemoteServerConfigurable;
+import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerConfigurationType;
+import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
+import com.intellij.remoteServer.impl.configuration.deployment.ModuleDeploymentSourceImpl;
+import com.intellij.util.text.UniqueNameGenerator;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @author michael.golubev
+ */
+public class CloudAccountSelectionEditor<SC extends CloudConfigurationBase,
+  DC extends CloudDeploymentNameConfiguration,
+  ST extends ServerType<SC>> implements Disposable {
+
+  private static final Logger LOG = Logger.getInstance("#" + CloudAccountSelectionEditor.class.getName());
+
+  private JComboBox myServerComboBox;
+  private JPanel myServerConfigurablePanel;
+  private JPanel myMainPanel;
+
+  private final ST myCloudType;
+
+  private RemoteServer<SC> myNewServer;
+  private RemoteServerConfigurable myServerConfigurable;
+
+  protected CloudAccountSelectionEditor(ST cloudType) {
+    myCloudType = cloudType;
+  }
+
+  private void createUIComponents() {
+    myServerConfigurablePanel = createServerConfigurablePanel();
+  }
+
+  public void initUI() {
+    myServerComboBox.addActionListener(new ActionListener() {
+
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        onAccountSelectionChanged();
+      }
+    });
+
+    for (RemoteServer<SC> server : RemoteServersManager.getInstance().getServers(myCloudType)) {
+      myServerComboBox.addItem(new ServerItem(server));
+    }
+    myServerComboBox.addItem(new ServerItem(myNewServer));
+  }
+
+  private void onAccountSelectionChanged() {
+    myServerConfigurablePanel.setVisible(getSelectedServerItem().isNew());
+  }
+
+  protected JPanel createServerConfigurablePanel() {
+    myNewServer = RemoteServersManager.getInstance().createServer(myCloudType, generateServerName());
+    myServerConfigurable = new RemoteServerConfigurable(myNewServer, null, true);
+    myServerConfigurablePanel = (JPanel)myServerConfigurable.createComponent();
+    return myServerConfigurablePanel;
+  }
+
+  private String generateServerName() {
+    return UniqueNameGenerator.generateUniqueName(myCloudType.getPresentableName(), new Condition<String>() {
+
+      @Override
+      public boolean value(String s) {
+        for (RemoteServer<?> server : RemoteServersManager.getInstance().getServers()) {
+          if (server.getName().equals(s)) {
+            return false;
+          }
+        }
+        return true;
+      }
+    });
+  }
+
+  public DeployToServerRunConfiguration<SC, DC> createRunConfiguration(Module module, DC deploymentConfiguration) {
+    Project project = module.getProject();
+
+    RemoteServer<SC> server = getServer();
+    if (server == null) {
+      return null;
+    }
+
+    if (getSelectedServerItem().isNew()) {
+      RemoteServersManager.getInstance().addServer(server);
+    }
+
+    String serverName = server.getName();
+
+    String name = generateRunConfigurationName(serverName, module.getName());
+
+    final RunManagerEx runManager = RunManagerEx.getInstanceEx(project);
+    final RunnerAndConfigurationSettings runSettings
+      = runManager.createRunConfiguration(name, getRunConfigurationType().getConfigurationFactories()[0]);
+
+    final DeployToServerRunConfiguration<SC, DC> result = (DeployToServerRunConfiguration<SC, DC>)runSettings.getConfiguration();
+
+    runManager.addConfiguration(runSettings, false);
+    runManager.setSelectedConfiguration(runSettings);
+
+    result.setServerName(serverName);
+
+    final ModulePointer modulePointer = ModulePointerManager.getInstance(project).create(module);
+    result.setDeploymentSource(new ModuleDeploymentSourceImpl(modulePointer));
+
+    result.setDeploymentConfiguration(deploymentConfiguration);
+
+    return result;
+  }
+
+  protected String generateRunConfigurationName(String serverName, String moduleName) {
+    return CloudBundle.getText("run.configuration.name", serverName, moduleName);
+  }
+
+  protected void handleError(ConfigurationException e) {
+    LOG.info(e);
+  }
+
+  public RemoteServer<SC> getServer() {
+    try {
+      return doGetServer();
+    }
+    catch (ConfigurationException e) {
+      handleError(e);
+      return null;
+    }
+  }
+
+  private RemoteServer<SC> doGetServer() throws ConfigurationException {
+    ServerItem serverItem = getSelectedServerItem();
+    if (serverItem.isNew()) {
+      myServerConfigurable.apply();
+      myNewServer.setName(myServerConfigurable.getDisplayName());
+    }
+    return serverItem.getServer();
+  }
+
+  public void validate() throws ConfigurationException {
+    doGetServer();
+  }
+
+  private ServerItem getSelectedServerItem() {
+    return (ServerItem)myServerComboBox.getSelectedItem();
+  }
+
+  private DeployToServerConfigurationType getRunConfigurationType() {
+    String id = DeployToServerConfigurationType.getId(myCloudType);
+    for (ConfigurationType configurationType : ConfigurationType.CONFIGURATION_TYPE_EP.getExtensions()) {
+      if (configurationType instanceof DeployToServerConfigurationType) {
+        DeployToServerConfigurationType deployConfigurationType = (DeployToServerConfigurationType)configurationType;
+        if (deployConfigurationType.getId().equals(id)) {
+          return deployConfigurationType;
+        }
+      }
+    }
+    return null;
+  }
+
+  public JPanel getMainPanel() {
+    return myMainPanel;
+  }
+
+  @Override
+  public void dispose() {
+    myServerConfigurable.disposeUIResources();
+  }
+
+  private class ServerItem {
+
+    private final RemoteServer<SC> myServer;
+
+    public ServerItem(RemoteServer<SC> server) {
+      myServer = server;
+    }
+
+    public boolean isNew() {
+      return myServer == myNewServer;
+    }
+
+    public RemoteServer<SC> getServer() {
+      return myServer;
+    }
+
+    @Override
+    public String toString() {
+      return isNew() ? "New account..." : myServer.getName();
+    }
+  }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudSupportConfigurableBase.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudSupportConfigurableBase.java
index e27a892..4aecb25 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudSupportConfigurableBase.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudSupportConfigurableBase.java
@@ -1,39 +1,24 @@
 package com.intellij.remoteServer.util;
 
 import com.intellij.ProjectTopics;
-import com.intellij.execution.RunManagerEx;
-import com.intellij.execution.RunnerAndConfigurationSettings;
-import com.intellij.execution.configurations.ConfigurationType;
 import com.intellij.ide.util.frameworkSupport.FrameworkSupportConfigurable;
 import com.intellij.ide.util.frameworkSupport.FrameworkSupportModel;
 import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModulePointer;
-import com.intellij.openapi.module.ModulePointerManager;
-import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.openapi.project.ModuleAdapter;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.startup.StartupManager;
 import com.intellij.openapi.ui.MessageType;
-import com.intellij.openapi.util.Condition;
-import com.intellij.remoteServer.ServerType;
+import com.intellij.openapi.util.Disposer;
 import com.intellij.remoteServer.configuration.RemoteServer;
-import com.intellij.remoteServer.configuration.RemoteServersManager;
-import com.intellij.remoteServer.impl.configuration.RemoteServerConfigurable;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerConfigurationType;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
-import com.intellij.remoteServer.impl.configuration.deployment.ModuleDeploymentSourceImpl;
 import com.intellij.remoteServer.runtime.Deployment;
 import com.intellij.remoteServer.runtime.ServerConnection;
 import com.intellij.remoteServer.runtime.ServerConnector;
 import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
 import com.intellij.util.concurrency.Semaphore;
 import com.intellij.util.messages.MessageBusConnection;
-import com.intellij.util.text.UniqueNameGenerator;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.util.Collection;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -43,43 +28,24 @@
 public abstract class CloudSupportConfigurableBase<
   SC extends CloudConfigurationBase,
   DC extends CloudDeploymentNameConfiguration,
-  ST extends ServerType<SC>,
   SR extends CloudMultiSourceServerRuntimeInstance<DC, ?, ?, ?>>
   extends FrameworkSupportConfigurable {
 
   private final Project myModelProject;
-  private RemoteServer<SC> myNewServer;
-  private ST myCloudType;
-  private RemoteServerConfigurable myServerConfigurable;
-  private JPanel myServerConfigurablePanel;
 
   private boolean myInitialized = false;
 
-  public CloudSupportConfigurableBase(FrameworkSupportModel frameworkSupportModel, ST cloudType) {
+  public CloudSupportConfigurableBase(FrameworkSupportModel frameworkSupportModel) {
     myModelProject = frameworkSupportModel.getProject();
-    myCloudType = cloudType;
   }
 
   @Override
   public void dispose() {
-    myServerConfigurable.disposeUIResources();
+    Disposer.dispose(getAccountSelectionEditor());
   }
 
   protected void initUI() {
-    JComboBox serverComboBox = getServerComboBox();
-
-    serverComboBox.addActionListener(new ActionListener() {
-
-      @Override
-      public void actionPerformed(ActionEvent e) {
-        onAccountSelectionChanged();
-      }
-    });
-
-    for (RemoteServer<SC> server : RemoteServersManager.getInstance().getServers(myCloudType)) {
-      serverComboBox.addItem(new ServerItem(server));
-    }
-    serverComboBox.addItem(new ServerItem(myNewServer));
+    getAccountSelectionEditor().initUI();
   }
 
   protected void reloadExistingApplications() {
@@ -137,21 +103,6 @@
     }
   }
 
-  private ServerItem getSelectedServerItem() {
-    return (ServerItem)getServerComboBox().getSelectedItem();
-  }
-
-  private void onAccountSelectionChanged() {
-    myServerConfigurablePanel.setVisible(getSelectedServerItem().isNew());
-  }
-
-  protected JPanel createServerConfigurablePanel() {
-    myNewServer = RemoteServersManager.getInstance().createServer(myCloudType, generateServerName());
-    myServerConfigurable = new RemoteServerConfigurable(myNewServer, null, true);
-    myServerConfigurablePanel = (JPanel)myServerConfigurable.createComponent();
-    return myServerConfigurablePanel;
-  }
-
   protected void showMessage(String message, MessageType messageType) {
     getNotifier().showMessage(message, messageType);
   }
@@ -160,77 +111,8 @@
     return myModelProject;
   }
 
-  private String generateServerName() {
-    return UniqueNameGenerator.generateUniqueName(myCloudType.getPresentableName(), new Condition<String>() {
-
-      @Override
-      public boolean value(String s) {
-        for (RemoteServer<?> server : RemoteServersManager.getInstance().getServers()) {
-          if (server.getName().equals(s)) {
-            return false;
-          }
-        }
-        return true;
-      }
-    });
-  }
-
-  private DeployToServerConfigurationType getRunConfigurationType() {
-    String id = DeployToServerConfigurationType.getId(myCloudType);
-    for (ConfigurationType configurationType : ConfigurationType.CONFIGURATION_TYPE_EP.getExtensions()) {
-      if (configurationType instanceof DeployToServerConfigurationType) {
-        DeployToServerConfigurationType deployConfigurationType = (DeployToServerConfigurationType)configurationType;
-        if (deployConfigurationType.getId().equals(id)) {
-          return deployConfigurationType;
-        }
-      }
-    }
-    return null;
-  }
-
   protected RemoteServer<SC> getServer() {
-    ServerItem serverItem = getSelectedServerItem();
-    if (serverItem.isNew()) {
-      try {
-        myServerConfigurable.apply();
-        myNewServer.setName(myServerConfigurable.getDisplayName());
-      }
-      catch (ConfigurationException e) {
-        showMessage(e.getMessage(), MessageType.ERROR);
-        return null;
-      }
-    }
-    return serverItem.getServer();
-  }
-
-  protected DeployToServerRunConfiguration<SC, DC> createRunConfiguration(String name, Module module, DC deploymentConfiguration) {
-    Project project = module.getProject();
-
-    RemoteServer<SC> server = getServer();
-
-    if (getSelectedServerItem().isNew()) {
-      RemoteServersManager.getInstance().addServer(server);
-    }
-
-    String serverName = server.getName();
-
-    final RunManagerEx runManager = RunManagerEx.getInstanceEx(project);
-    final RunnerAndConfigurationSettings runSettings
-      = runManager.createRunConfiguration(name, getRunConfigurationType().getConfigurationFactories()[0]);
-
-    final DeployToServerRunConfiguration<SC, DC> result = (DeployToServerRunConfiguration<SC, DC>)runSettings.getConfiguration();
-
-    runManager.addConfiguration(runSettings, false);
-    runManager.setSelectedConfiguration(runSettings);
-
-    result.setServerName(serverName);
-
-    final ModulePointer modulePointer = ModulePointerManager.getInstance(project).create(module);
-    result.setDeploymentSource(new ModuleDeploymentSourceImpl(modulePointer));
-
-    result.setDeploymentConfiguration(deploymentConfiguration);
-
-    return result;
+    return getAccountSelectionEditor().getServer();
   }
 
   protected void runOnModuleAdded(final Module module, final Runnable runnable) {
@@ -250,36 +132,14 @@
     }
   }
 
-  protected abstract JComboBox getExistingComboBox();
+  protected abstract CloudAccountSelectionEditor<SC, DC, ?> getAccountSelectionEditor();
 
-  protected abstract JComboBox getServerComboBox();
+  protected abstract JComboBox getExistingComboBox();
 
   protected abstract void updateApplicationUI();
 
   protected abstract CloudNotifier getNotifier();
 
-  protected class ServerItem {
-
-    private final RemoteServer<SC> myServer;
-
-    public ServerItem(RemoteServer<SC> server) {
-      myServer = server;
-    }
-
-    public boolean isNew() {
-      return myServer == myNewServer;
-    }
-
-    public RemoteServer<SC> getServer() {
-      return myServer;
-    }
-
-    @Override
-    public String toString() {
-      return isNew() ? "New account..." : myServer.getName();
-    }
-  }
-
   protected abstract class ConnectionTask<T> extends CloudConnectionTask<T, SC, DC, SR> {
 
     public ConnectionTask(String title) {
diff --git a/platform/structure-view-api/src/com/intellij/ide/structureView/TextEditorBasedStructureViewModel.java b/platform/structure-view-api/src/com/intellij/ide/structureView/TextEditorBasedStructureViewModel.java
index 5cef3a5..34641fe 100644
--- a/platform/structure-view-api/src/com/intellij/ide/structureView/TextEditorBasedStructureViewModel.java
+++ b/platform/structure-view-api/src/com/intellij/ide/structureView/TextEditorBasedStructureViewModel.java
@@ -19,8 +19,8 @@
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.editor.event.CaretAdapter;
 import com.intellij.openapi.editor.event.CaretEvent;
-import com.intellij.openapi.editor.event.CaretListener;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
@@ -71,7 +71,7 @@
     myPsiFile = file;
 
     if (editor != null) {
-      EditorFactory.getInstance().getEventMulticaster().addCaretListener(new CaretListener() {
+      EditorFactory.getInstance().getEventMulticaster().addCaretListener(new CaretAdapter() {
         @Override
         public void caretPositionChanged(CaretEvent e) {
           if (e.getEditor().equals(myEditor)) {
diff --git a/platform/testFramework/src/com/intellij/mock/Mock.java b/platform/testFramework/src/com/intellij/mock/Mock.java
index d511f2f..f0ca6a1 100644
--- a/platform/testFramework/src/com/intellij/mock/Mock.java
+++ b/platform/testFramework/src/com/intellij/mock/Mock.java
@@ -453,9 +453,10 @@
       throw new UnsupportedOperationException();
     }
 
+    @NotNull
     @Override
     public String getPath() {
-      return null;
+      throw new UnsupportedOperationException();
     }
 
     @Override
diff --git a/platform/testFramework/src/com/intellij/mock/MockModule.java b/platform/testFramework/src/com/intellij/mock/MockModule.java
index 9a0065c..e0eaf7a 100644
--- a/platform/testFramework/src/com/intellij/mock/MockModule.java
+++ b/platform/testFramework/src/com/intellij/mock/MockModule.java
@@ -1,5 +1,17 @@
 /*
- * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 package com.intellij.mock;
 
@@ -37,26 +49,31 @@
     return "";
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleRuntimeScope(final boolean includeTests) {
     return new MockGlobalSearchScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleScope() {
     return new MockGlobalSearchScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleScope(boolean includeTests) {
     return new MockGlobalSearchScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleTestsWithDependentsScope() {
     return new MockGlobalSearchScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependenciesAndLibrariesScope(final boolean includeTests) {
     return new MockGlobalSearchScope();
@@ -64,26 +81,31 @@
     //throw new UnsupportedOperationException( "Method getModuleWithDependenciesAndLibrariesScope is not yet implemented in " + getClass().getName());
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependenciesScope() {
     return new MockGlobalSearchScope();
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleContentWithDependenciesScope() {
     throw new UnsupportedOperationException("Method getModuleContentWithDependenciesScope is not yet implemented in " + getClass().getName());
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleContentScope() {
     throw new UnsupportedOperationException("Method getModuleContentScope is not yet implemented in " + getClass().getName());
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithDependentsScope() {
     throw new UnsupportedOperationException("Method getModuleWithDependentsScope is not yet implemented in " + getClass().getName());
   }
 
+  @NotNull
   @Override
   public GlobalSearchScope getModuleWithLibrariesScope() {
     throw new UnsupportedOperationException("Method getModuleWithLibrariesScope is not yet implemented in " + getClass().getName());
diff --git a/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java b/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java
index f6c02f5..9f31bbb 100644
--- a/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java
+++ b/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -90,6 +90,7 @@
     return ourFileSystem;
   }
 
+  @NotNull
   @Override
   public String getPath() {
     String prefix = myParent == null ? "MOCK_ROOT:" : myParent.getPath();
@@ -101,6 +102,7 @@
     return myIsWritable;
   }
 
+  @Override
   public void setWritable(boolean b) {
     myIsWritable = b;
   }
diff --git a/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java b/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java
index 2eeee2e..19870bf 100644
--- a/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java
+++ b/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -113,9 +113,10 @@
 
     @Override
     public boolean isDirectory() {
-      return myChildren.size() != 0;
+      return !myChildren.isEmpty();
     }
 
+    @NotNull
     @Override
     public String getPath() {
       final MockVirtualFileSystem.MyVirtualFile parent = getParent();
diff --git a/platform/testFramework/testSrc/com/intellij/psi/formatter/FormatterTestCase.java b/platform/testFramework/src/com/intellij/psi/formatter/FormatterTestCase.java
similarity index 100%
rename from platform/testFramework/testSrc/com/intellij/psi/formatter/FormatterTestCase.java
rename to platform/testFramework/src/com/intellij/psi/formatter/FormatterTestCase.java
diff --git a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
index 5d658bf..3ae9b8d 100644
--- a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
+++ b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
@@ -30,7 +30,6 @@
 import com.intellij.openapi.editor.impl.DefaultEditorTextRepresentationHelper;
 import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
 import com.intellij.openapi.editor.impl.softwrap.mapping.SoftWrapApplianceManager;
-import com.intellij.openapi.util.Segment;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
@@ -309,13 +308,13 @@
   public static void setCaretsAndSelection(Editor editor, CaretAndSelectionState caretsState) {
     CaretModel caretModel = editor.getCaretModel();
     if (caretModel.supportsMultipleCarets()) {
-      List<LogicalPosition> caretPositions = new ArrayList<LogicalPosition>();
-      List<Segment> selections = new ArrayList<Segment>();
+      List<CaretState> states = new ArrayList<CaretState>(caretsState.carets.size());
       for (CaretInfo caret : caretsState.carets) {
-        caretPositions.add(caret.position == null ? null : editor.offsetToLogicalPosition(caret.getCaretOffset(editor.getDocument())));
-        selections.add(caret.selection == null ? null : caret.selection);
+        states.add(new CaretState(caret.position == null ? null : editor.offsetToLogicalPosition(caret.getCaretOffset(editor.getDocument())),
+                                  caret.selection == null ? null : editor.offsetToLogicalPosition(caret.selection.getStartOffset()),
+                                  caret.selection == null ? null : editor.offsetToLogicalPosition(caret.selection.getEndOffset())));
       }
-      caretModel.setCaretsAndSelections(caretPositions, selections);
+      caretModel.setCaretsAndSelections(states);
     }
     else {
       assertEquals("Multiple carets are not supported by the model", 1, caretsState.carets.size());
@@ -326,6 +325,9 @@
       if (caret.selection != null) {
         editor.getSelectionModel().setSelection(caret.selection.getStartOffset(), caret.selection.getEndOffset());
       }
+      else {
+        editor.getSelectionModel().removeSelection();
+      }
     }
     if (caretsState.blockSelection != null) {
       editor.getSelectionModel().setBlockSelection(editor.offsetToLogicalPosition(caretsState.blockSelection.getStartOffset()),
diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
index e1e6907..59b8d4b 100644
--- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -308,14 +308,14 @@
   protected static Module doCreateRealModuleIn(String moduleName, final Project project, final ModuleType moduleType) {
     final VirtualFile baseDir = project.getBaseDir();
     assertNotNull(baseDir);
-    final File moduleFile = new File(baseDir.getPath().replace('/', File.separatorChar),
-                                     moduleName + ModuleFileType.DOT_DEFAULT_EXTENSION);
+    final File moduleFile = new File(FileUtil.toSystemDependentName(baseDir.getPath()), moduleName + ModuleFileType.DOT_DEFAULT_EXTENSION);
     FileUtil.createIfDoesntExist(moduleFile);
     myFilesToDelete.add(moduleFile);
     return new WriteAction<Module>() {
       @Override
-      protected void run(Result<Module> result) throws Throwable {
-        final VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(moduleFile);
+      protected void run(@NotNull Result<Module> result) throws Throwable {
+        VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(moduleFile);
+        assertNotNull(virtualFile);
         Module module = ModuleManager.getInstance(project).newModule(virtualFile.getPath(), moduleType.getId());
         module.getModuleFile();
         result.setResult(module);
diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
index 785c587..104c55e 100644
--- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
@@ -639,6 +639,14 @@
     String actualText = StringUtil.convertLineSeparators(actual.trim());
     Assert.assertEquals(expectedText, actualText);
   }
+  
+  public static void assertExists(File file){
+    assertTrue("File should exists " + file, file.exists());
+  }
+
+  public static void assertDoesntExist(File file){
+    assertFalse("File should not exists " + file, file.exists());
+  }
 
   protected String getTestName(boolean lowercaseFirstLetter) {
     String name = getName();
diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java
index 0c24d8b..af4c7f6 100644
--- a/platform/util/src/com/intellij/icons/AllIcons.java
+++ b/platform/util/src/com/intellij/icons/AllIcons.java
@@ -817,8 +817,11 @@
     public static final Icon Parameter = IconLoader.getIcon("/nodes/parameter.png"); // 16x16
     public static final Icon PinToolWindow = IconLoader.getIcon("/nodes/pinToolWindow.png"); // 13x13
     public static final Icon Plugin = IconLoader.getIcon("/nodes/plugin.png"); // 16x16
+    public static final Icon PluginJB = IconLoader.getIcon("/nodes/pluginJB.png"); // 16x16
     public static final Icon Pluginnotinstalled = IconLoader.getIcon("/nodes/pluginnotinstalled.png"); // 16x16
     public static final Icon Pluginobsolete = IconLoader.getIcon("/nodes/pluginobsolete.png"); // 16x16
+    public static final Icon PluginRestart = IconLoader.getIcon("/nodes/pluginRestart.png"); // 16x16
+    public static final Icon PluginUpdate = IconLoader.getIcon("/nodes/pluginUpdate.png"); // 16x16
     public static final Icon Pointcut = IconLoader.getIcon("/nodes/pointcut.png"); // 16x16
     public static final Icon PpFile = IconLoader.getIcon("/nodes/ppFile.png"); // 16x16
     public static final Icon PpInvalid = IconLoader.getIcon("/nodes/ppInvalid.png"); // 16x16
diff --git a/platform/util/src/com/intellij/openapi/diff/LineTokenizer.java b/platform/util/src/com/intellij/openapi/diff/LineTokenizer.java
index 7aafcac..e86567b 100644
--- a/platform/util/src/com/intellij/openapi/diff/LineTokenizer.java
+++ b/platform/util/src/com/intellij/openapi/diff/LineTokenizer.java
@@ -17,18 +17,14 @@
 
 import com.intellij.util.ArrayUtil;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class LineTokenizer {
+public class LineTokenizer extends LineTokenizerBase<String> {
   private final char[] myChars;
   private final String myText;
 
-  private int myIndex = 0;
-  @Nullable private String myLineSeparator = null;
-
   public LineTokenizer(@NotNull String text) {
     myChars = text.toCharArray();
     myText = text;
@@ -36,71 +32,35 @@
 
   @NotNull
   public String[] execute() {
-    List<String> lines = new ArrayList<String>();
-    while (notAtEnd()) {
-      int begin = myIndex;
-      skipToEOL();
-      int endIndex = myIndex;
-      boolean appendNewLine = false;
-
-      if (notAtEnd() && isAtEOL()) {
-        if (myChars[endIndex] == '\n') {
-          endIndex++;
-        }
-        else {
-          appendNewLine = true;
-        }
-        skipEOL();
-      }
-
-      String line = myText.substring(begin, endIndex);
-      if (appendNewLine) {
-        line += "\n";
-      }
-      lines.add(line);
-    }
+    ArrayList<String> lines = new ArrayList<String>();
+    doExecute(lines);
     return ArrayUtil.toStringArray(lines);
   }
 
-  private void skipEOL() {
-    int eolStart = myIndex;
-    boolean nFound = false;
-    boolean rFound = false;
-    while (notAtEnd()) {
-      boolean n = myChars[myIndex] == '\n';
-      boolean r = myChars[myIndex] == '\r';
-      if (!n && !r) {
-        break;
-      }
-      if ((nFound && n) || (rFound && r)) {
-        break;
-      }
-      nFound |= n;
-      rFound |= r;
-      myIndex++;
+  @Override
+  protected void addLine(List<String> lines, int start, int end, boolean appendNewLine) {
+    if (appendNewLine) {
+      lines.add(myText.substring(start, end) + "\n");
     }
-    if (myLineSeparator == null) {
-      myLineSeparator = new String(myChars, eolStart, myIndex - eolStart);
+    else {
+      lines.add(myText.substring(start, end));
     }
   }
 
-  @Nullable
-  public String getLineSeparator() {
-    return myLineSeparator;
+  @Override
+  protected char charAt(int index) {
+    return myChars[index];
   }
 
-  private void skipToEOL() {
-    while (notAtEnd() && !isAtEOL()) {
-      myIndex++;
-    }
+  @Override
+  protected int length() {
+    return myChars.length;
   }
 
-  private boolean notAtEnd() {
-    return myIndex < myChars.length;
-  }
-
-  private boolean isAtEOL() {
-    return myChars[myIndex] == '\r' || myChars[myIndex] == '\n';
+  @NotNull
+  @Override
+  protected String substring(int start, int end) {
+    return myText.substring(start, end);
   }
 
   @NotNull
diff --git a/platform/util/src/com/intellij/openapi/diff/LineTokenizerBase.java b/platform/util/src/com/intellij/openapi/diff/LineTokenizerBase.java
new file mode 100644
index 0000000..85fed35
--- /dev/null
+++ b/platform/util/src/com/intellij/openapi/diff/LineTokenizerBase.java
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public abstract class LineTokenizerBase<T> {
+  private int myIndex = 0;
+  private int myLineSeparatorStart = -1;
+  private int myLineSeparatorEnd = -1;
+
+  protected abstract void addLine(List<T> lines, int start, int end, boolean appendNewLine);
+
+  protected abstract char charAt(int index);
+
+  protected abstract int length();
+
+  @NotNull
+  protected abstract String substring(int start, int end);
+
+  public void doExecute(List<T> lines) {
+    while (notAtEnd()) {
+      int begin = myIndex;
+      skipToEOL();
+      int endIndex = myIndex;
+      boolean appendNewLine = false;
+
+      if (notAtEnd() && isAtEOL()) {
+        if (charAt(endIndex) == '\n') {
+          endIndex++;
+        }
+        else {
+          appendNewLine = true;
+        }
+        skipEOL();
+      }
+
+      addLine(lines, begin, endIndex, appendNewLine);
+    }
+  }
+
+  private void skipEOL() {
+    int eolStart = myIndex;
+    boolean nFound = false;
+    boolean rFound = false;
+    while (notAtEnd()) {
+      boolean n = charAt(myIndex) == '\n';
+      boolean r = charAt(myIndex) == '\r';
+      if (!n && !r) {
+        break;
+      }
+      if ((nFound && n) || (rFound && r)) {
+        break;
+      }
+      nFound |= n;
+      rFound |= r;
+      myIndex++;
+    }
+    if (myLineSeparatorStart == -1) {
+      myLineSeparatorStart = eolStart;
+      myLineSeparatorEnd = myIndex;
+    }
+  }
+
+  @Nullable
+  public String getLineSeparator() {
+    if (myLineSeparatorStart == -1) return null;
+    return substring(myLineSeparatorStart, myLineSeparatorEnd);
+  }
+
+  private void skipToEOL() {
+    while (notAtEnd() && !isAtEOL()) {
+      myIndex++;
+    }
+  }
+
+  private boolean notAtEnd() {
+    return myIndex < length();
+  }
+
+  private boolean isAtEOL() {
+    return charAt(myIndex) == '\r' || charAt(myIndex) == '\n';
+  }
+}
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/openapi/diff/ex/DiffFragment.java b/platform/util/src/com/intellij/openapi/diff/ex/DiffFragment.java
index 791d4a0..e1a4852 100644
--- a/platform/util/src/com/intellij/openapi/diff/ex/DiffFragment.java
+++ b/platform/util/src/com/intellij/openapi/diff/ex/DiffFragment.java
@@ -15,31 +15,37 @@
  */
 package com.intellij.openapi.diff.ex;
 
+import com.intellij.openapi.diff.impl.string.DiffString;
+import com.intellij.openapi.diff.impl.string.DiffStringBuilder;
 import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
 
 public class DiffFragment {
   public static DiffFragment[] EMPTY_ARRAY = new DiffFragment[0];
 
-  private final String myText1;
-  private final String myText2;
+  @Nullable private CharSequence myText1;
+  @Nullable private CharSequence myText2;
   private boolean myIsModified;
 
-  private StringBuilder myText1Builder;
-  private StringBuilder myText2Builder;
+  @TestOnly
+  public DiffFragment(@Nullable String text1, @Nullable String text2) {
+    this(DiffString.createNullable(text1), DiffString.createNullable(text2));
+  }
 
-  public DiffFragment(String text1, String text2) {
+  public DiffFragment(@Nullable DiffString text1, @Nullable DiffString text2) {
     myText1 = text1;
     myText2 = text2;
     myIsModified = (text1 == null || text2 == null || !text1.equals(text2));
   }
 
-  public static boolean isEmpty(DiffFragment fragment) {
-    return StringUtil.length(fragment.getText1()) == 0 &&
-           StringUtil.length(fragment.getText2()) == 0;
+  public boolean isEmpty() {
+    return StringUtil.isEmpty(myText1) && StringUtil.isEmpty(myText2);
   }
 
   /**
-   * Makes sence if both texts are not null
+   * Makes sense if both texts are not null
    * @return true if both texts are considered modified, false otherwise
    */
   public boolean isModified() {
@@ -50,34 +56,70 @@
     myIsModified = modified;
   }
 
-  public void appendText1(String str) {
-    assert myText1 != null;
-    if (myText1Builder == null) {
-      myText1Builder = new StringBuilder(myText1);
+  public void appendText1(@Nullable DiffString str) {
+    if (str == null) return;
+    if (myText1 instanceof DiffStringBuilder) {
+      ((DiffStringBuilder)myText1).append(str);
+      return;
     }
-    myText1Builder.append(str);
+
+    if (myText1 instanceof DiffString) {
+      DiffString text1 = (DiffString)myText1;
+      if (DiffString.canInplaceConcatenate(text1, str)) {
+        myText1 = DiffString.concatenate(text1, str);
+      }
+      else {
+        DiffStringBuilder builder = new DiffStringBuilder(text1.length() + str.length());
+        builder.append(text1);
+        builder.append(str);
+        myText1 = builder;
+      }
+      return;
+    }
+
+    throw new IllegalStateException("Bad DiffFragment: " + (myText1 != null ? myText1.getClass() : "null"));
   }
 
-  public void appendText2(String str) {
-    assert myText2 != null;
-    if (myText2Builder == null) {
-      myText2Builder = new StringBuilder(myText2);
+  public void appendText2(@Nullable DiffString str) {
+    if (str == null) return;
+    if (myText2 instanceof DiffStringBuilder) {
+      ((DiffStringBuilder)myText2).append(str);
+      return;
     }
-    myText2Builder.append(str);
+
+    if (myText2 instanceof DiffString) {
+      DiffString text2 = (DiffString)myText2;
+      if (DiffString.canInplaceConcatenate(text2, str)) {
+        myText2 = DiffString.concatenate(text2, str);
+      }
+      else {
+        DiffStringBuilder builder = new DiffStringBuilder(text2.length() + str.length());
+        builder.append(text2);
+        builder.append(str);
+        myText2 = builder;
+      }
+      return;
+    }
+
+    throw new IllegalStateException("Bad DiffFragment: " + (myText2 != null ? myText2.getClass() : "null"));
   }
 
-  /**
-   * null if absent
-   */
-  public String getText1() {
-    return myText1Builder != null ? myText1Builder.toString() : myText1;
+  @Nullable
+  public DiffString getText1() {
+    if (myText1 == null) return null;
+    if (myText1 instanceof DiffString) return (DiffString)myText1;
+    if (myText1 instanceof DiffStringBuilder) return ((DiffStringBuilder)myText1).toDiffString();
+
+    throw new IllegalStateException("Bad DiffFragment: " + myText1.getClass());
   }
-  
-  /**
-   * null if absent
-   */
-  public String getText2() {
-    return myText2Builder != null ? myText2Builder.toString() : myText2;
+
+  @Nullable
+  public DiffString getText2() {
+    if (myText2 == null) return null;
+    if (myText2 instanceof DiffString) return (DiffString)myText2;
+    if (myText2 instanceof DiffStringBuilder) return ((DiffStringBuilder)myText2).toDiffString();
+
+    throw new IllegalStateException("Bad DiffFragment: " + myText2.getClass());
   }
 
   /**
@@ -85,23 +127,30 @@
    * @return true iff both texts are present and {@link #isModified()}
    */
   public boolean isChange() {
-    return myText1 != null && myText2 != null && isModified();
+    return (myText1 != null) && (myText2 != null) && isModified();
   }
 
   /**
    * @return true iff both texts are present and not {@link #isModified()}
    */
   public boolean isEqual() {
-    return myText1 != null && myText2 != null && !isModified();
+    return (myText1 != null) && (myText2 != null) && !isModified();
   }
 
-  public static DiffFragment unchanged(String text1, String text2) {
+  @TestOnly
+  public static DiffFragment unchanged(@Nullable String text1, @Nullable String text2) {
+    return unchanged(DiffString.createNullable(text1), DiffString.createNullable(text2));
+  }
+
+  public static DiffFragment unchanged(@Nullable DiffString text1, @Nullable DiffString text2) {
+    if (text1 == null) text1 = DiffString.EMPTY;
+    if (text2 == null) text2 = DiffString.EMPTY;
     DiffFragment result = new DiffFragment(text1, text2);
     result.setModified(false);
     return result;
   }
 
   public boolean isOneSide() {
-    return myText1 == null || myText2 == null;
+    return (myText1 == null) || (myText2 == null);
   }
 }
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java b/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java
index 0767413..b38c827 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java
@@ -16,6 +16,7 @@
 package com.intellij.openapi.diff.impl;
 
 import com.intellij.CommonBundle;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.highlighting.Util;
@@ -24,18 +25,30 @@
 import com.intellij.openapi.diff.impl.processing.Word;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.diff.Diff;
 import com.intellij.util.diff.FilesTooBigForDiffException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
 
 public abstract class ComparisonPolicy {
+  public static final ComparisonPolicy DEFAULT = new DefaultPolicy();
+  public static final ComparisonPolicy TRIM_SPACE = new TrimSpacePolicy();
+  public static final ComparisonPolicy IGNORE_SPACE = new IgnoreSpacePolicy();
+  public static final ComparisonPolicy[] COMPARISON_POLICIES = new ComparisonPolicy[]{DEFAULT, IGNORE_SPACE, TRIM_SPACE};
+
   private final String myName;
 
   protected ComparisonPolicy(final String name) {
     myName = name;
   }
 
-  public DiffFragment[] buildFragments(String[] strings1, String[] strings2) throws FilesTooBigForDiffException {
+  public String getName() {
+    return myName;
+  }
+
+  @NotNull
+  public DiffFragment[] buildFragments(@NotNull DiffString[] strings1, @NotNull DiffString[] strings2) throws FilesTooBigForDiffException {
     DiffFragmentBuilder builder = new DiffFragmentBuilder(strings1, strings2);
     Object[] wrappers1 = getWrappers(strings1);
     Object[] wrappers2 = getWrappers(strings2);
@@ -43,7 +56,9 @@
     return builder.buildFragments(Util.concatEquals(change, wrappers1, wrappers2));
   }
 
-  public DiffFragment[] buildDiffFragmentsFromLines(String[] lines1, String[] lines2) throws FilesTooBigForDiffException {
+  @NotNull
+  public DiffFragment[] buildDiffFragmentsFromLines(@NotNull DiffString[] lines1, @NotNull DiffString[] lines2)
+    throws FilesTooBigForDiffException {
     DiffFragmentBuilder builder = new DiffFragmentBuilder(lines1, lines2);
     Object[] wrappers1 = getLineWrappers(lines1);
     Object[] wrappers2 = getLineWrappers(lines2);
@@ -51,19 +66,52 @@
     return builder.buildFragments(change);
   }
 
-  public static final ComparisonPolicy DEFAULT = new ComparisonPolicy(CommonBundle.message("comparison.policy.default.name")) {
+  @NotNull
+  public DiffFragment createFragment(@Nullable DiffString text1, @Nullable DiffString text2) {
+    text1 = toNull(text1);
+    text2 = toNull(text2);
+    if (text1 == null && text2 == null) return new DiffFragment(DiffString.EMPTY, DiffString.EMPTY);
+    DiffFragment result = new DiffFragment(text1, text2);
+    if (text1 != null && text2 != null) {
+      result.setModified(!getWrapper(text1).equals(getWrapper(text2)));
+    }
+    return result;
+  }
+
+  @NotNull
+  public abstract DiffFragment createFragment(@NotNull Word word1, @NotNull Word word2);
+
+  @NotNull
+  protected abstract Object[] getWrappers(@NotNull DiffString[] strings);
+
+  @NotNull
+  protected abstract Object[] getLineWrappers(@NotNull DiffString[] lines);
+
+  @NotNull
+  private Object getWrapper(@NotNull DiffString text) {
+    return getWrappers(new DiffString[]{text})[0];
+  }
+
+  private static class DefaultPolicy extends ComparisonPolicy {
+    public DefaultPolicy() {
+      super(CommonBundle.message("comparison.policy.default.name"));
+    }
+
+    @NotNull
     @Override
-    protected Object[] getWrappers(String[] strings) {
+    protected Object[] getWrappers(@NotNull DiffString[] strings) {
       return strings;
     }
 
+    @NotNull
     @Override
-    protected Object[] getLineWrappers(String[] lines) {
+    protected Object[] getLineWrappers(@NotNull DiffString[] lines) {
       return lines;
     }
 
+    @NotNull
     @Override
-    public DiffFragment createFragment(Word word1, Word word2) {
+    public DiffFragment createFragment(@NotNull Word word1, @NotNull Word word2) {
       return createFragment(word1.getText(), word2.getText());
     }
 
@@ -71,18 +119,24 @@
     public String toString() {
       return "DEFAULT";
     }
-  };
+  }
 
-  public static final ComparisonPolicy TRIM_SPACE = new ComparisonPolicy(CommonBundle.message("comparison.policy.trim.space.name")) {
+  private static class TrimSpacePolicy extends ComparisonPolicy {
+    public TrimSpacePolicy() {
+      super(CommonBundle.message("comparison.policy.trim.space.name"));
+    }
+
+    @NotNull
     @Override
-    protected Object[] getLineWrappers(String[] lines) {
+    protected Object[] getLineWrappers(@NotNull DiffString[] lines) {
       return trimStrings(lines);
     }
 
+    @NotNull
     @Override
-    public DiffFragment createFragment(Word word1, Word word2) {
-      String text1 = word1.getText();
-      String text2 = word2.getText();
+    public DiffFragment createFragment(@NotNull Word word1, @NotNull Word word2) {
+      DiffString text1 = word1.getText();
+      DiffString text2 = word2.getText();
       if (word1.isWhitespace() && word2.isWhitespace() &&
           word1.atEndOfLine() && word2.atEndOfLine()) {
         return DiffFragment.unchanged(text1, text2);
@@ -90,16 +144,17 @@
       return createFragment(text1, text2);
     }
 
+    @NotNull
     @Override
-    protected Object[] getWrappers(String[] strings) {
+    protected Object[] getWrappers(@NotNull DiffString[] strings) {
       Object[] result = new Object[strings.length];
       boolean atBeginning = true;
       for (int i = 0; i < strings.length; i++) {
-        String string = strings[i];
-        String wrapper = atBeginning ? StringUtil.trimLeading(string) : string;
-        if (StringUtil.endsWithChar(wrapper, '\n')) {
+        DiffString string = strings[i];
+        DiffString wrapper = atBeginning ? string.trimLeading() : string;
+        if (wrapper.endsWith('\n')) {
           atBeginning = true;
-          wrapper = StringUtil.trimTrailing(wrapper);
+          wrapper = wrapper.trimTrailing();
         }
         else {
           atBeginning = false;
@@ -109,128 +164,66 @@
       return result;
     }
 
-
-
     @SuppressWarnings({"HardCodedStringLiteral"})
     public String toString() {
       return "TRIM";
     }
-  };
-
-  public static final ComparisonPolicy IGNORE_SPACE = new IgnoreSpacePolicy();
-
-  private static String toNotNull(String text) {
-    return text == null ? "" : text;
   }
 
-  protected abstract Object[] getWrappers(String[] strings);
-
-  protected abstract Object[] getLineWrappers(String[] lines);
-
-  protected Object[] trimStrings(String[] strings) {
-    Object[] result = new Object[strings.length];
-    for (int i = 0; i < strings.length; i++) {
-      String string = strings[i];
-      result[i] = string.trim();
-    }
-    return result;
-  }
-
-  public DiffFragment createFragment(String text1, String text2) {
-    text1 = toNull(text1);
-    text2 = toNull(text2);
-    if (text1 == null && text2 == null) return new DiffFragment("", "");
-    DiffFragment result = new DiffFragment(text1, text2);
-    if (text1 != null && text2 != null) {
-      result.setModified(!getWrapper(text1).equals(getWrapper(text2)));
-    }
-    return result;
-  }
-
-  private String toNull(String text1) {
-    return text1 == null || text1.isEmpty() ? null : text1;
-  }
-
-  private Object getWrapper(String text) {
-    return getWrappers(new String[]{text})[0];
-  }
-
-  public boolean isEqual(DiffFragment fragment) {
-    if (fragment.isOneSide()) return false;
-    Object[] wrappers = getLineWrappers(new String[]{fragment.getText1(), fragment.getText2()});
-    return Comparing.equal(wrappers[0], wrappers[1]);
-  }
-
-  public Word createFormatting(String text, TextRange textRange) {
-    return new Formatting(text, textRange);
-  }
-
-  public abstract DiffFragment createFragment(Word word1, Word word2);
-
-  public String getName() {
-    return myName;
-  }
-
-  public static final ComparisonPolicy[] COMPARISON_POLICIES = new ComparisonPolicy[]{DEFAULT, IGNORE_SPACE, TRIM_SPACE};
-  
-  public static ComparisonPolicy[] getAllInstances() {
-    return COMPARISON_POLICIES;
-  }
-
-  private static class IgnoreSpacePolicy extends ComparisonPolicy implements DiffCorrection.FragmentProcessor<DiffCorrection.FragmentsCollector> {
+  private static class IgnoreSpacePolicy extends ComparisonPolicy
+    implements DiffCorrection.FragmentProcessor<DiffCorrection.FragmentsCollector> {
     public IgnoreSpacePolicy() {
       super(CommonBundle.message("comparison.policy.ignore.spaces.name"));
     }
 
+    @NotNull
     @Override
-    protected Object[] getLineWrappers(String[] lines) {
+    protected Object[] getLineWrappers(@NotNull DiffString[] lines) {
       Object[] result = new Object[lines.length];
       for (int i = 0; i < lines.length; i++) {
-        String line = lines[i];
+        DiffString line = lines[i];
         result[i] = getWrapper(line);
       }
       return result;
     }
 
+    @NotNull
     @Override
-    public DiffFragment[] buildFragments(String[] strings1, String[] strings2) throws FilesTooBigForDiffException {
+    public DiffFragment[] buildFragments(@NotNull DiffString[] strings1, @NotNull DiffString[] strings2)
+      throws FilesTooBigForDiffException {
       DiffFragment[] fragments = super.buildFragments(strings1, strings2);
       DiffCorrection.FragmentsCollector collector = new DiffCorrection.FragmentsCollector();
       collector.processAll(fragments, this);
       return collector.toArray();
     }
 
-    private Object getWrapper(String line) {
-      StringBuilder builder = new StringBuilder(line.length());
-      for (int i = 0; i < line.length(); i++) {
-        char aChar = line.charAt(i);
-        if (StringUtil.isWhiteSpace(aChar)) continue;
-        builder.append(aChar);
-      }
-      return builder.toString();
+    @NotNull
+    private static Object getWrapper(@NotNull DiffString line) {
+      return line.skipSpaces();
     }
 
+    @NotNull
     @Override
-    public DiffFragment createFragment(Word word1, Word word2) {
-      String text1 = word1.getText();
-      String text2 = word2.getText();
-      return word1.isWhitespace() && word2.isWhitespace() ?
-             DiffFragment.unchanged(text1, text2) :
-             createFragment(text1, text2);
+    public DiffFragment createFragment(@NotNull Word word1, @NotNull Word word2) {
+      DiffString text1 = word1.getText();
+      DiffString text2 = word2.getText();
+      return word1.isWhitespace() && word2.isWhitespace() ? DiffFragment.unchanged(text1, text2) : createFragment(text1, text2);
     }
 
+    @NotNull
     @Override
-    public DiffFragment createFragment(String text1, String text2) {
-      String toCompare1 = toNotNull(text1);
-      String toCompare2 = toNotNull(text2);
+    public DiffFragment createFragment(DiffString text1, DiffString text2) {
+      DiffString toCompare1 = toNotNull(text1);
+      DiffString toCompare2 = toNotNull(text2);
       if (getWrapper(toCompare1).equals(getWrapper(toCompare2))) {
         return DiffFragment.unchanged(toCompare1, toCompare2);
       }
       return new DiffFragment(text1, text2);
     }
 
+    @NotNull
     @Override
-    protected Object[] getWrappers(String[] strings) {
+    protected Object[] getWrappers(@NotNull DiffString[] strings) {
       return trimStrings(strings);
     }
 
@@ -240,21 +233,76 @@
     }
 
     @Override
-    public void process(DiffFragment fragment, DiffCorrection.FragmentsCollector collector) {
+    public void process(@NotNull DiffFragment fragment, @NotNull DiffCorrection.FragmentsCollector collector) {
       if (fragment.isEqual()) {
         collector.add(fragment);
         return;
       }
       if (fragment.isOneSide()) {
         FragmentSide side = FragmentSide.chooseSide(fragment);
-        String text = side.getText(fragment);
-        String trimed = text.trim();
+        DiffString text = side.getText(fragment);
+        DiffString trimed = text.trim();
         if (trimed.isEmpty()) {
-          collector.add(side.createFragment(text, "", false));
+          collector.add(side.createFragment(text, DiffString.EMPTY, false));
           return;
         }
       }
       collector.add(fragment);
     }
   }
+
+  @Nullable
+  private static DiffString toNull(@Nullable DiffString text1) {
+    return text1 == null || text1.isEmpty() ? null : text1;
+  }
+
+  @NotNull
+  private static DiffString toNotNull(@Nullable DiffString text) {
+    return text == null ? DiffString.EMPTY : text;
+  }
+
+  @NotNull
+  protected Object[] trimStrings(@NotNull DiffString[] strings) {
+    Object[] result = new Object[strings.length];
+    for (int i = 0; i < strings.length; i++) {
+      DiffString string = strings[i];
+      result[i] = string.trim();
+    }
+    return result;
+  }
+
+  public boolean isEqual(@NotNull DiffFragment fragment) {
+    if (fragment.isOneSide()) return false;
+    Object[] wrappers = getLineWrappers(new DiffString[]{fragment.getText1(), fragment.getText2()});
+    return Comparing.equal(wrappers[0], wrappers[1]);
+  }
+
+  @NotNull
+  public Word createFormatting(@NotNull DiffString text, @NotNull TextRange textRange) {
+    return new Formatting(text, textRange);
+  }
+
+  public static ComparisonPolicy[] getAllInstances() {
+    return COMPARISON_POLICIES;
+  }
+
+  @NotNull
+  @TestOnly
+  protected Object[] getWrappers(@NotNull String[] lines) {
+    DiffString[] unsafeStrings = new DiffString[lines.length];
+    for (int i = 0; i < lines.length; i++) {
+      unsafeStrings[i] = DiffString.createNullable(lines[i]);
+    }
+    return getWrappers(unsafeStrings);
+  }
+
+  @NotNull
+  @TestOnly
+  protected Object[] getLineWrappers(@NotNull String[] lines) {
+    DiffString[] unsafeStrings = new DiffString[lines.length];
+    for (int i = 0; i < lines.length; i++) {
+      unsafeStrings[i] = DiffString.createNullable(lines[i]);
+    }
+    return getLineWrappers(unsafeStrings);
+  }
 }
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/DiffFragmentBuilder.java b/platform/util/src/com/intellij/openapi/diff/impl/DiffFragmentBuilder.java
index 3b6a00b..64630e9 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/DiffFragmentBuilder.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/DiffFragmentBuilder.java
@@ -21,9 +21,12 @@
 package com.intellij.openapi.diff.impl;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.util.diff.Diff;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.LinkedList;
 import java.util.List;
@@ -56,25 +59,26 @@
 
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.DiffFragmentBuilder");
 
-  private final String[] mySource1;
-  private final String[] mySource2;
+  @NotNull private final DiffString[] mySource1;
+  @NotNull private final DiffString[] mySource2;
   private int myLastLine1 = 1;
   private int myLastLine2 = 1;
-  private final List<DiffFragment> myData = new LinkedList<DiffFragment>();
+  @NotNull private final List<DiffFragment> myData = new LinkedList<DiffFragment>();
 
-  public DiffFragmentBuilder(String[] source1, String[] source2) {
+  public DiffFragmentBuilder(@NotNull DiffString[] source1, @NotNull DiffString[] source2) {
     mySource1 = source1;
     mySource2 = source2;
     init();
   }
 
+  @NotNull
   private List<DiffFragment> getFragments() {
     return myData;
   }
 
   private void finish() {
-    String text1 = null;
-    String text2 = null;
+    DiffString text1 = null;
+    DiffString text2 = null;
     if (myLastLine1 <= mySource1.length) {
       text1 = concatenate(mySource1, myLastLine1, mySource1.length);
     }
@@ -91,10 +95,10 @@
     myLastLine1 = myLastLine2 = 1;
   }
 
-  private void append(int line, TextRange range) {
+  private void append(int line, @NotNull TextRange range) {
     LOG.debug("DiffFragmentBuilder.append(" + line + "," + range + "), modified:");
-    String text1 = null;
-    String text2 = null;
+    DiffString text1 = null;
+    DiffString text2 = null;
     int start = range.getStartOffset();
     int end = range.getEndOffset();
     if (myLastLine1 <= line) {
@@ -111,10 +115,10 @@
     myLastLine2 = end + 1;
   }
 
-  private void change(TextRange range1, TextRange range2) {
+  private void change(@NotNull TextRange range1, @NotNull TextRange range2) {
     LOG.debug("DiffFragmentBuilder.change(" + range1 + "," + range2 + ")");
 
-    String text1 = null, text2 = null;
+    DiffString text1 = null, text2 = null;
     int start1 = range1.getStartOffset();
     int end1 = range1.getEndOffset();
     int start2 = range2.getStartOffset();
@@ -134,11 +138,11 @@
     myLastLine2 = end2 + 1;
   }
 
-  private void delete(TextRange range, int line) {
+  private void delete(@NotNull TextRange range, int line) {
     LOG.debug("DiffFragmentBuilder.delete(" + range + "," + line + ")");
 
-    String text1 = null;
-    String text2 = null;
+    DiffString text1 = null;
+    DiffString text2 = null;
     int start = range.getStartOffset();
     int end = range.getEndOffset();
     if (myLastLine1 < start) {
@@ -155,15 +159,13 @@
     myLastLine2 = line + 1;
   }
 
-  private static String concatenate(String[] strings, int start, int end) {
-    int len = 0;
-    for (int i = start - 1; i < end; i++) len += strings[i] == null ? 0 : strings[i].length();
-    StringBuilder buffer = new StringBuilder(len);
-    for (int i = start - 1; i < end; i++) buffer.append(strings[i]);
-    return buffer.toString();
+  @NotNull
+  private static DiffString concatenate(@NotNull DiffString[] strings, int start, int end) {
+    return DiffString.concatenate(strings, start - 1, end - start + 1);
   }
 
-  public DiffFragment[] buildFragments(Diff.Change change) {
+  @NotNull
+  public DiffFragment[] buildFragments(@Nullable Diff.Change change) {
     while (change != null) {
       if (change.inserted > 0 && change.deleted > 0) {
         change(
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/fragments/LineFragment.java b/platform/util/src/com/intellij/openapi/diff/impl/fragments/LineFragment.java
index 705be4f..57399b5 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/fragments/LineFragment.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/fragments/LineFragment.java
@@ -16,10 +16,12 @@
 package com.intellij.openapi.diff.impl.fragments;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.util.TextDiffTypeEnum;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
@@ -147,9 +149,10 @@
     return myChildren == null || myChildren.isEmpty() ? null : myChildren.iterator();
   }
 
-  public String getText(String text, FragmentSide side) {
+  @NotNull
+  public DiffString getText(@NotNull DiffString text, @NotNull FragmentSide side) {
     TextRange range = getRange(side);
-    return range.substring(text);
+    return text.substring(range.getStartOffset(), range.getEndOffset());
   }
 
 
@@ -186,7 +189,7 @@
     }
     boolean hasLineChildren = false;
     boolean hasInlineChildren = false;
-    for (; iterator.hasNext();) {
+    while(iterator.hasNext()) {
       Fragment fragment = iterator.next();
       boolean lineChild = fragment instanceof LineFragment;
       hasLineChildren |= lineChild;
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/highlighting/FragmentSide.java b/platform/util/src/com/intellij/openapi/diff/impl/highlighting/FragmentSide.java
index 620a8f3..efdf589 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/highlighting/FragmentSide.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/highlighting/FragmentSide.java
@@ -16,19 +16,23 @@
 package com.intellij.openapi.diff.impl.highlighting;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public enum FragmentSide {
 
   SIDE1(0, 0) {
     @Override
-    public String getText(DiffFragment fragment) {
+    @Nullable
+    public DiffString getText(@NotNull DiffFragment fragment) {
       return fragment.getText1();
     }
 
     @Override
-    protected DiffFragment createDiffFragment(String text, String otherText) {
+    @NotNull
+    protected DiffFragment createDiffFragment(@Nullable DiffString text, @Nullable DiffString otherText) {
       return new DiffFragment(text, otherText);
     }
 
@@ -40,12 +44,14 @@
 
   SIDE2(1, 2) {
     @Override
-    public String getText(DiffFragment fragment) {
+    @Nullable
+    public DiffString getText(@NotNull DiffFragment fragment) {
       return fragment.getText2();
     }
 
     @Override
-    protected DiffFragment createDiffFragment(String text, String otherText) {
+    @NotNull
+    protected DiffFragment createDiffFragment(@Nullable DiffString text, @Nullable DiffString otherText) {
       return new DiffFragment(otherText, text);
     }
 
@@ -65,15 +71,18 @@
     myMergeIndex = mergeIndex;
   }
 
-  public DiffFragment createFragment(String text, String otherText, boolean modified) {
+  @NotNull
+  public DiffFragment createFragment(@Nullable DiffString text, @Nullable DiffString otherText, boolean modified) {
     DiffFragment fragment = createDiffFragment(text, otherText);
     if (!fragment.isOneSide()) fragment.setModified(modified);
     return fragment;
   }
 
-  public abstract String getText(DiffFragment fragment);
+  @Nullable
+  public abstract DiffString getText(@NotNull DiffFragment fragment);
   public abstract FragmentSide otherSide();
-  protected abstract DiffFragment createDiffFragment(String text, String otherText);
+  @NotNull
+  protected abstract DiffFragment createDiffFragment(@Nullable DiffString text, @Nullable DiffString otherText);
 
   public int getIndex() {
     return myIndex;
@@ -83,7 +92,8 @@
     return myMergeIndex;
   }
 
-  public String getOtherText(DiffFragment fragment) {
+  @Nullable
+  public DiffString getOtherText(@NotNull DiffFragment fragment) {
     return otherSide().getText(fragment);
   }
 
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/highlighting/Util.java b/platform/util/src/com/intellij/openapi/diff/impl/highlighting/Util.java
index 83cfa98..15c24d3 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/highlighting/Util.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/highlighting/Util.java
@@ -16,11 +16,14 @@
 package com.intellij.openapi.diff.impl.highlighting;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.diff.Diff;
 import gnu.trove.TIntHashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -33,14 +36,15 @@
   public static final TIntHashSet DELIMITERS_SET = new TIntHashSet();
 
   static {
-    char[] delimiters = Util.DELIMITERS.toCharArray();
+    char[] delimiters = DELIMITERS.toCharArray();
     for (int i = 0; i < delimiters.length; i++) {
       char delimiter = delimiters[i];
-      Util.DELIMITERS_SET.add(delimiter);
+      DELIMITERS_SET.add(delimiter);
     }
   }
 
-  static String[] splitByWord(String string) {
+  @NotNull
+  static String[] splitByWord(@NotNull String string) {
     BufferedStringList stringList = new BufferedStringList();
     StringTokenizer tokenizer = new StringTokenizer(string, DELIMITERS, true);
     while (tokenizer.hasMoreTokens()) {
@@ -62,19 +66,19 @@
     return stringList.toArray();
   }
 
-  static boolean isSpaceOnly(DiffFragment fragment) {
+  static boolean isSpaceOnly(@NotNull DiffFragment fragment) {
     return isSpaceOnly(fragment.getText1()) && isSpaceOnly(fragment.getText2());
   }
 
-  private static boolean isSpaceOnly(String string) {
+  private static boolean isSpaceOnly(@Nullable DiffString string) {
     if (string == null) return true;
-    for (int i = 0; i < string.length(); i++) if (!Character.isWhitespace(string.charAt(i))) return false;
-    return true;
+    return string.isEmptyOrSpaces();
   }
 
-  static DiffFragment[] splitByLines(DiffFragment fragment) {
-    String[] lines1 = splitByLines(fragment.getText1());
-    String[] lines2 = splitByLines(fragment.getText2());
+  @NotNull
+  static DiffFragment[] splitByLines(@NotNull DiffFragment fragment) {
+    DiffString[] lines1 = splitByLines(fragment.getText1());
+    DiffString[] lines2 = splitByLines(fragment.getText2());
     if (lines1 != null && lines2 != null && lines1.length != lines2.length) {
       LOG.error("1:<" + fragment.getText1() + "> 2:<" + fragment.getText2() + ">");
     }
@@ -86,22 +90,16 @@
     return lines;
   }
 
-  private static String[] splitByLines(String string) {
+  @Nullable
+  private static DiffString[] splitByLines(@Nullable DiffString string) {
     if (string == null) return null;
-    if (string.indexOf('\n') == -1) return new String[]{string};
-    String[] strings = string.split("\n", -1);
-    for (int i = 0; i < strings.length - 1; i++) {
-      strings[i] += "\n";
-    }
-    if (StringUtil.endsWithChar(string, '\n')) {
-      String[] result = new String[strings.length - 1];
-      System.arraycopy(strings, 0, result, 0, strings.length - 1);
-      return result;
-    }
-    return strings;
+    if (string.indexOf('\n') == -1) return new DiffString[]{string};
+
+    return string.tokenize();
   }
 
-  public static DiffFragment[][] splitByUnchangedLines(DiffFragment[] fragments) {
+  @NotNull
+  public static DiffFragment[][] splitByUnchangedLines(@NotNull DiffFragment[] fragments) {
     List2D result = new List2D();
     for (int i = 0; i < fragments.length; i++) {
       DiffFragment fragment = fragments[i];
@@ -109,8 +107,10 @@
         result.add(fragment);
         continue;
       }
-      String text1 = fragment.getText1();
-      String text2 = fragment.getText2();
+      DiffString text1 = fragment.getText1();
+      DiffString text2 = fragment.getText2();
+      assert text1 != null;
+      assert text2 != null;
       if (StringUtil.endsWithChar(text1, '\n') && StringUtil.endsWithChar(text2, '\n')) {
         result.add(fragment);
         result.newRow();
@@ -139,7 +139,7 @@
     return result.toArray();
   }
 
-  public static Diff.Change concatEquals(Diff.Change change, Object[] left, Object[] right) {
+  public static Diff.Change concatEquals(Diff.Change change, @NotNull Object[] left, @NotNull Object[] right) {
     MyChange startChange = new MyChange(0, 0, 0, 0);
     MyChange lastChange = startChange;
     while (change != null) {
@@ -187,7 +187,7 @@
     return startChange.link;
   }
 
-  static int calcShift(Object[] list, int limit, int start, int length) {
+  static int calcShift(@NotNull Object[] list, int limit, int start, int length) {
     int shift = start - limit;
     for (int i = 0; i < shift; i++) {
       if (!list[limit + i].equals(list[start + length - shift + i])) return 0;
@@ -195,20 +195,22 @@
     return -shift;
   }
 
-  public static DiffFragment unite(DiffFragment fragment1, DiffFragment fragment2) {
+  @NotNull
+  public static DiffFragment unite(@NotNull DiffFragment fragment1, @NotNull DiffFragment fragment2) {
     LOG.assertTrue(isSameType(fragment1, fragment2));
     if (!fragment1.isOneSide()) {
-      String unitedText1 = fragment1.getText1() + fragment2.getText1();
-      String unitedText2 = fragment1.getText2() + fragment2.getText2();
+      DiffString unitedText1 = DiffString.concatenateNullable(fragment1.getText1(), fragment2.getText1());
+      DiffString unitedText2 = DiffString.concatenateNullable(fragment1.getText2(), fragment2.getText2());
       LOG.assertTrue(fragment1.isEqual() == fragment2.isEqual());
       return fragment1.isEqual() ? DiffFragment.unchanged(unitedText1, unitedText2) :
           new DiffFragment(unitedText1, unitedText2);
     }
     FragmentSide side = FragmentSide.chooseSide(fragment1);
-    return side.createFragment(side.getText(fragment1) + side.getText(fragment2), null, fragment1.isModified());
+    return side
+      .createFragment(DiffString.concatenateNullable(side.getText(fragment1), side.getText(fragment2)), null, fragment1.isModified());
   }
 
-  public static boolean isSameType(DiffFragment fragment1, DiffFragment fragment2) {
+  public static boolean isSameType(@NotNull DiffFragment fragment1, @NotNull DiffFragment fragment2) {
     if (fragment1.isEqual()) return fragment2.isEqual();
     if (fragment1.isChange()) return fragment2.isChange();
     if (fragment1.getText1() == null) return fragment2.getText1() == null;
@@ -217,52 +219,46 @@
     return false;
   }
 
-  public static String getText(DiffFragment[] fragments, FragmentSide side) {
-    StringBuffer buffer = new StringBuffer();
+  @NotNull
+  public static DiffString getText(@NotNull DiffFragment[] fragments, @NotNull FragmentSide side) {
+    DiffString[] data = new DiffString[fragments.length];
     for (int i = 0; i < fragments.length; i++) {
       DiffFragment fragment = fragments[i];
-      String text = side.getText(fragment);
-      if (text != null) buffer.append(text);
+      data[i] = side.getText(fragment);
     }
-    return buffer.toString();
+    return DiffString.concatenate(data);
   }
 
-  public static DiffFragment concatenate(DiffFragment[] line) {
+  @NotNull
+  public static DiffFragment concatenate(@NotNull DiffFragment[] line) {
     return concatenate(line, 0, line.length);
   }
 
-  public static DiffFragment concatenate(DiffFragment[] line, int from, int to) {
-    String[] data1 = new String[to - from];
-    String[] data2 = new String[to - from];
+  @NotNull
+  public static DiffFragment concatenate(@NotNull DiffFragment[] line, int from, int to) {
+    DiffString[] data1 = new DiffString[to - from];
+    DiffString[] data2 = new DiffString[to - from];
 
-    int len1 = 0;
-    int len2 = 0;
     boolean isEqual = true;
     for (int i = 0; i < to - from; i++) {
-      isEqual &= line[i + from].isEqual();
-      data1[i] = line[i + from].getText1();
-      data2[i] = line[i + from].getText2();
-      len1 += data1[i] == null ? 0 : data1[i].length();
-      len2 += data2[i] == null ? 0 : data2[i].length();
+      DiffFragment fragment = line[from + i];
+      isEqual &= fragment.isEqual();
+      data1[i] = fragment.getText1();
+      data2[i] = fragment.getText2();
     }
 
-    StringBuilder buffer1 = new StringBuilder(len1);
-    StringBuilder buffer2 = new StringBuilder(len2);
-    for (int i = 0; i < to - from; i++) {
-      if (data1[i] != null) buffer1.append(data1[i]);
-      if (data2[i] != null) buffer2.append(data2[i]);
-    }
-
-    String text1 = notEmptyContent(buffer1);
-    String text2 = notEmptyContent(buffer2);
+    DiffString text1 = notEmptyContent(DiffString.concatenate(data1));
+    DiffString text2 = notEmptyContent(DiffString.concatenate(data2));
     return isEqual ? DiffFragment.unchanged(text1, text2) : new DiffFragment(text1, text2);
   }
 
-  private static String notEmptyContent(StringBuilder buffer) {
-    return buffer.length() > 0 ? buffer.toString() : null;
+  @Nullable
+  private static DiffString notEmptyContent(@NotNull DiffString string) {
+    return string.length() > 0 ? string : null;
   }
 
-  public static DiffFragment[][] uniteFormattingOnly(DiffFragment[][] lines) {
+  @NotNull
+  public static DiffFragment[][] uniteFormattingOnly(@NotNull DiffFragment[][] lines) {
     List2D result = new List2D();
     for (int i = 0; i < lines.length; i++) {
       DiffFragment[] line = lines[i];
@@ -276,20 +272,20 @@
     return result.toArray();
   }
 
-  private static boolean areEqualOrFormatting(DiffFragment[] fragments) {
+  private static boolean areEqualOrFormatting(@NotNull DiffFragment[] fragments) {
     for (int i = 0; i < fragments.length; i++) {
       DiffFragment fragment = fragments[i];
       if (fragment.isEqual()) continue;
       for (int side = 0;  side < 2; side++) {
-        String text = FragmentSide.fromIndex(side).getText(fragment);
-        if (text == null || text.trim().isEmpty()) continue;
+        DiffString text = FragmentSide.fromIndex(side).getText(fragment);
+        if (text == null || text.isEmptyOrSpaces()) continue;
         return false;
       }
     }
     return true;
   }
 
-  private static boolean areEqual(DiffFragment[] fragments) {
+  private static boolean areEqual(@NotNull DiffFragment[] fragments) {
     for (int i = 0; i < fragments.length; i++) {
       DiffFragment fragment = fragments[i];
       if (!fragment.isEqual()) return false;
@@ -297,7 +293,8 @@
     return true;
   }
 
-  public static DiffFragment[] cutFirst(DiffFragment[] fragments) {
+  @NotNull
+  public static DiffFragment[] cutFirst(@NotNull DiffFragment[] fragments) {
     fragments = transformHeadInsert(fragments, FragmentSide.SIDE1);
     fragments = transformHeadInsert(fragments, FragmentSide.SIDE2);
 
@@ -307,10 +304,10 @@
       for (int i = 0; i < fragments.length; i++) {
         DiffFragment fragment = fragments[i];
         if (fragment == null) continue;
-        String text = side.getText(fragment);
+        DiffString text = side.getText(fragment);
         if (text == null || text.isEmpty()) continue;
         text = text.length() > 1 ? text.substring(1) : null;
-        String otherText = side.getOtherText(fragment);
+        DiffString otherText = side.getOtherText(fragment);
         if (otherText == null && text == null) {
           fragments[i] = null;
           nullCount++;
@@ -330,7 +327,8 @@
     return result;
   }
 
-  private static DiffFragment[] transformHeadInsert(DiffFragment[] fragments, FragmentSide side) {
+  @NotNull
+  private static DiffFragment[] transformHeadInsert(@NotNull DiffFragment[] fragments, @NotNull FragmentSide side) {
     // transforms {abc}abcd into a{bca}bcd
     if (fragments.length >= 2) {
       DiffFragment first = fragments[0];
@@ -341,15 +339,15 @@
       if (side.getText(first) != null) {
         return fragments;
       }
-      String rightText = side.getOtherText(first);
-      String secondText = side.getText(second);
+      DiffString rightText = side.getOtherText(first);
+      DiffString secondText = side.getText(second);
       if (!Comparing.equal(side.getOtherText(second), secondText)) {
         return fragments;
       }
       if (secondText.charAt(0) == rightText.charAt(0)) {
         List<DiffFragment> result = new ArrayList<DiffFragment>();
         result.add(side.createFragment(rightText.substring(0, 1), rightText.substring(0, 1), false));
-        result.add(side.createFragment(null, rightText.substring(1) + secondText.substring(0, 1), true));
+        result.add(side.createFragment(null, DiffString.concatenate(rightText.substring(1), secondText.substring(0, 1)), true));
         result.add(side.createFragment(secondText.substring(1), secondText.substring(1), second.isModified()));
         result.addAll(Arrays.asList(fragments).subList(2, fragments.length));
         return result.toArray(new DiffFragment[result.size()]);
@@ -363,11 +361,11 @@
       super(line0, line1, deleted, inserted, null);
     }
 
-    public MyChange copyNext(Diff.Change change) {
+    public MyChange copyNext(@NotNull Diff.Change change) {
       return copyNext(change, 0);
     }
 
-    public MyChange copyNext(Diff.Change change, int shift) {
+    public MyChange copyNext(@NotNull Diff.Change change, int shift) {
       MyChange result = new MyChange(change.line0 + shift, change.line1 + shift, change.deleted, change.inserted);
       setNext(result);
       return result;
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/ByWord.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/ByWord.java
index 21740dc..9aa43f5 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/processing/ByWord.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/processing/ByWord.java
@@ -20,13 +20,16 @@
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.highlighting.Util;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.util.diff.Diff;
 import com.intellij.util.diff.FilesTooBigForDiffException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
 
 import java.util.ArrayList;
 
-public class ByWord implements DiffPolicy{
+public class ByWord implements DiffPolicy {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.processing.ByWord");
   private final ComparisonPolicy myComparisonPolicy;
 
@@ -34,8 +37,15 @@
     myComparisonPolicy = comparisonPolicy;
   }
 
+  @NotNull
+  @TestOnly
+  public DiffFragment[] buildFragments(@NotNull String text1, @NotNull String text2) throws FilesTooBigForDiffException {
+    return buildFragments(DiffString.create(text1), DiffString.create(text2));
+  }
+
+  @NotNull
   @Override
-  public DiffFragment[] buildFragments(String text1, String text2) throws FilesTooBigForDiffException {
+  public DiffFragment[] buildFragments(@NotNull DiffString text1, @NotNull DiffString text2) throws FilesTooBigForDiffException {
     Word[] words1 = buildWords(text1, myComparisonPolicy);
     Word[] words2 = buildWords(text2, myComparisonPolicy);
     Diff.Change change = Diff.buildChanges(words1, words2);
@@ -54,8 +64,8 @@
       } else if (change.deleted == 0) {
         processOneside(version2, change.inserted);
       } else {
-        String prefix1 = version1.getCurrentWordPrefix();
-        String prefix2 = version2.getCurrentWordPrefix();
+        DiffString prefix1 = version1.getCurrentWordPrefix();
+        DiffString prefix2 = version2.getCurrentWordPrefix();
         if (!prefix1.isEmpty() || !prefix2.isEmpty())
           result.add(myComparisonPolicy.createFragment(prefix1, prefix2));
         result.addChangedWords(change.deleted, change.inserted);
@@ -66,7 +76,7 @@
     result.addTails();
     DiffFragment[] fragments = result.getFragments();
     DiffFragment firstFragment = fragments[0];
-    if (DiffFragment.isEmpty(firstFragment)) {
+    if (firstFragment.isEmpty()) {
       DiffFragment[] newFragments = new DiffFragment[fragments.length - 1];
       System.arraycopy(fragments, 1, newFragments, 0, newFragments.length);
       fragments = newFragments;
@@ -74,7 +84,7 @@
     return fragments;
   }
 
-  private int countNotWhitespaces(Word[] words) {
+  private static int countNotWhitespaces(@NotNull Word[] words) {
     int counter = 0;
     for (int i = 0; i < words.length; i++) {
       Word word = words[i];
@@ -83,7 +93,7 @@
     return counter;
   }
 
-  private int countEqual(Diff.Change change, Word[] words1, Word[] words2) {
+  private static int countEqual(Diff.Change change, @NotNull Word[] words1, @NotNull Word[] words2) {
     int counter = 0;
     int position1 = 0;
     int position2 = 0;
@@ -111,19 +121,26 @@
     return counter;
   }
 
-  private void processOneside(FragmentBuilder.Version version, int wordCount) {
-    String prefix = version.getCurrentWordPrefix();
+  private static void processOneside(@NotNull FragmentBuilder.Version version, int wordCount) {
+    DiffString prefix = version.getCurrentWordPrefix();
     version.addOneSide(prefix, wordCount);
   }
 
-  private void processEquals(int changed1, int changed2, FragmentBuilder result) throws FilesTooBigForDiffException {
+  private static void processEquals(int changed1, int changed2, @NotNull FragmentBuilder result) throws FilesTooBigForDiffException {
     while (result.getVersion1().getCurrentWordIndex() < changed1) {
       result.processEqual();
     }
     LOG.assertTrue(changed2 == result.getVersion2().getCurrentWordIndex());
   }
 
-  static Word[] buildWords(String text, ComparisonPolicy policy) {
+  @NotNull
+  @TestOnly
+  static Word[] buildWords(@NotNull String text, @NotNull ComparisonPolicy policy) {
+    return buildWords(DiffString.create(text), policy);
+  }
+
+  @NotNull
+  static Word[] buildWords(@NotNull DiffString text, @NotNull ComparisonPolicy policy) {
     ArrayList<Word> words = new ArrayList<Word>();
     if (text.isEmpty() || !Character.isWhitespace(text.charAt(0)))
       words.add(policy.createFormatting(text, TextRange.EMPTY_RANGE));
@@ -167,7 +184,7 @@
     private final DiffCorrection.ChangedSpace CORRECTION;
     private final ComparisonPolicy myComparisonPolicy;
 
-    public FragmentBuilder(Word[] words1, Word[] words2, ComparisonPolicy comparisonPolicy, String text1, String text2) {
+    public FragmentBuilder(@NotNull Word[] words1, @NotNull Word[] words2, @NotNull ComparisonPolicy comparisonPolicy, @NotNull DiffString text1, @NotNull DiffString text2) {
       myVersion1 = new Version(words1, text1, this, true);
       myVersion2 = new Version(words2, text2, this, false);
       BY_CHAR = new ByChar(comparisonPolicy);
@@ -175,24 +192,27 @@
       myComparisonPolicy = comparisonPolicy;
     }
 
+    @NotNull
     public DiffFragment[] getFragments() {
       return myFragments.toArray(new DiffFragment[myFragments.size()]);
     }
 
+    @NotNull
     public Version getVersion1() { return myVersion1; }
 
+    @NotNull
     public Version getVersion2() { return myVersion2; }
 
-    private void addAll(DiffFragment[] fragments) {
+    private void addAll(@NotNull DiffFragment[] fragments) {
       for (int i = 0; i < fragments.length; i++) {
         DiffFragment fragment = fragments[i];
         add(fragment);
       }
     }
 
-    private void add(DiffFragment fragment) {
-      String text1 = fragment.getText1();
-      String text2 = fragment.getText2();
+    private void add(@NotNull DiffFragment fragment) {
+      DiffString text1 = fragment.getText1();
+      DiffString text2 = fragment.getText2();
       if (text1 != null) myVersion1.addOffset(text1.length());
       if (text2 != null) myVersion2.addOffset(text2.length());
       if (fragment.isEqual() && !myFragments.isEmpty()) {
@@ -207,7 +227,7 @@
       myFragments.add(fragment);
     }
 
-    private void addEqual(Word word1, Word word2) throws FilesTooBigForDiffException {
+    private void addEqual(@NotNull Word word1, @NotNull Word word2) throws FilesTooBigForDiffException {
       addAll(CORRECTION.correct(new DiffFragment[]{myComparisonPolicy.createFragment(word1, word2)}));
     }
 
@@ -221,19 +241,20 @@
       myVersion2.incCurrentWord();
     }
 
-    private DiffFragment[] fragmentsByChar(String text1, String text2) throws FilesTooBigForDiffException {
+    @NotNull
+    private DiffFragment[] fragmentsByChar(@NotNull DiffString text1, @NotNull DiffString text2) throws FilesTooBigForDiffException {
       if (text1.isEmpty() && text2.isEmpty()) {
         return DiffFragment.EMPTY_ARRAY;
       }
-      final String side1 = myVersion1.getPrevChar() + text1;
-      final String side2 = myVersion2.getPrevChar() + text2;
+      final DiffString side1 = text1.preappend(myVersion1.getPrevChar());
+      final DiffString side2 = text2.preappend(myVersion2.getPrevChar());
       DiffFragment[] fragments = BY_CHAR.buildFragments(side1, side2);
       return Util.cutFirst(fragments);
     }
 
     private void addPostfixes() throws FilesTooBigForDiffException {
-      String postfix1 = myVersion1.getCurrentWordPostfixAndOneMore();
-      String postfix2 = myVersion2.getCurrentWordPostfixAndOneMore();
+      DiffString postfix1 = myVersion1.getCurrentWordPostfixAndOneMore();
+      DiffString postfix2 = myVersion2.getCurrentWordPostfixAndOneMore();
       int length1 = postfix1.length();
       int length2 = postfix2.length();
       DiffFragment wholePostfix = myComparisonPolicy.createFragment(postfix1, postfix2);
@@ -245,20 +266,23 @@
         DiffFragment[] fragments = BY_CHAR.buildFragments(postfix1, postfix2);
         DiffFragment firstFragment = fragments[0];
         if (firstFragment.isEqual()) {
-          final String text1 = cutLast(firstFragment.getText1(), length1);
-          final String text2 = cutLast(firstFragment.getText2(), length2);
+          final DiffString text1 = cutLast(firstFragment.getText1(), length1);
+          final DiffString text2 = cutLast(firstFragment.getText2(), length2);
           add(myComparisonPolicy.createFragment(text1, text2));
           //add(firstFragment);
         }
       }
     }
 
-    private String cutLast(String text, int length) {
+    @NotNull
+    private static DiffString cutLast(@NotNull DiffString text, int length) {
       if (text.length() < length) return text;
-      else return text.substring(0, text.length() - 1);
+      else {
+        return text.substring(0, text.length() - 1);
+      }
     }
 
-    private void addOneSide(String text, FragmentSide side) {
+    private void addOneSide(@NotNull DiffString text, @NotNull FragmentSide side) {
       DiffFragment fragment = side.createFragment(text, null, false);
       add(myComparisonPolicy.createFragment(fragment.getText1(), fragment.getText2()));
     }
@@ -270,8 +294,8 @@
     }
 
     public void addTails() throws FilesTooBigForDiffException {
-      String tail1 = myVersion1.getNotProcessedTail();
-      String tail2 = myVersion2.getNotProcessedTail();
+      DiffString tail1 = myVersion1.getNotProcessedTail();
+      DiffString tail2 = myVersion2.getNotProcessedTail();
       if (tail1.isEmpty() && tail2.isEmpty()) return;
       DiffFragment[] fragments = fragmentsByChar(tail1, tail2);
       if (!myFragments.isEmpty()) {
@@ -301,14 +325,14 @@
     }
 
     public static class Version {
-      private final Word[] myWords;
+      @NotNull private final Word[] myWords;
       private int myCurrentWord = 0;
       private int myOffset = 0;
-      private final String myText;
-      private final FragmentBuilder myBuilder;
+      @NotNull private final DiffString myText;
+      @NotNull private final FragmentBuilder myBuilder;
       private final FragmentSide mySide;
 
-      public Version(Word[] words, String text, FragmentBuilder builder, boolean delete) {
+      public Version(@NotNull Word[] words, @NotNull DiffString text, @NotNull FragmentBuilder builder, boolean delete) {
         myWords = words;
         myText = text;
         myBuilder = builder;
@@ -331,7 +355,8 @@
         incCurrentWord(1);
       }
 
-      public String getWordSequence(int wordCount) {
+      @NotNull
+      public DiffString getWordSequence(int wordCount) {
         int start = myWords[myCurrentWord].getStart();
         int end = myWords[myCurrentWord+wordCount-1].getEnd();
         return myText.substring(start, end);
@@ -341,22 +366,26 @@
         myCurrentWord += inserted;
       }
 
+      @NotNull
       public Word getCurrentWord() {
         return myWords[myCurrentWord];
       }
 
-      public String getCurrentWordPrefix() {
+      @NotNull
+      public DiffString getCurrentWordPrefix() {
         return getCurrentWord().getPrefix(getProcessedOffset());
       }
 
-      public String getCurrentWordPostfixAndOneMore() {
+      @NotNull
+      public DiffString getCurrentWordPostfixAndOneMore() {
         int nextStart = myCurrentWord < myWords.length - 1 ? myWords[myCurrentWord + 1].getStart() : myText.length();
         Word word = getCurrentWord();
-        String postfix = myText.substring(word.getEnd(), nextStart);
-        return postfix + (nextStart == myText.length() ? '\n' : myText.charAt(nextStart));
+        DiffString postfix = myText.substring(word.getEnd(), nextStart);
+        return postfix.append(nextStart == myText.length() ? '\n' : myText.charAt(nextStart));
       }
 
-      public String getNotProcessedTail() {
+      @NotNull
+      public DiffString getNotProcessedTail() {
         LOG.assertTrue(myCurrentWord == myWords.length);
         return myText.substring(myOffset, myText.length());
       }
@@ -365,7 +394,7 @@
         return myOffset == 0 ? '\n' : myText.charAt(myOffset - 1);
       }
 
-      public void addOneSide(String prefix, int wordCount) {
+      public void addOneSide(@NotNull DiffString prefix, int wordCount) {
         if (!prefix.isEmpty()) myBuilder.addOneSide(prefix, mySide);
         myBuilder.addOneSide(getWordSequence(wordCount), mySide);
         incCurrentWord(wordCount);
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/DiffCorrection.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/DiffCorrection.java
index ee8db1c..a97b1c5 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/processing/DiffCorrection.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/processing/DiffCorrection.java
@@ -16,7 +16,7 @@
 package com.intellij.openapi.diff.impl.processing;
 
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.diff.LineTokenizer;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
@@ -48,14 +48,18 @@
     }
 
     @Override
-    public void process(DiffFragment fragment, FragmentsCollector collector) throws FilesTooBigForDiffException {
+    public void process(@NotNull DiffFragment fragment, @NotNull FragmentsCollector collector) throws FilesTooBigForDiffException {
+      DiffString text1 = fragment.getText1();
+      DiffString text2 = fragment.getText2();
       if (!fragment.isEqual()) {
         if (myComparisonPolicy.isEqual(fragment))
-          fragment = myComparisonPolicy.createFragment(fragment.getText1(), fragment.getText2());
+          fragment = myComparisonPolicy.createFragment(text1, text2);
         collector.add(fragment);
       } else {
-        String[] lines1 = new LineTokenizer(fragment.getText1()).execute();
-        String[] lines2 = new LineTokenizer(fragment.getText2()).execute();
+        assert text1 != null;
+        assert text2 != null;
+        DiffString[] lines1 = text1.tokenize();
+        DiffString[] lines2 = text2.tokenize();
         LOG.assertTrue(lines1.length == lines2.length);
         for (int i = 0; i < lines1.length; i++)
           collector.addAll(myDiffPolicy.buildFragments(lines1[i], lines2[i]));
@@ -77,45 +81,39 @@
     }
 
     @Override
-    public void process(DiffFragment fragment, FragmentsCollector collector) throws FilesTooBigForDiffException {
+    public void process(@NotNull DiffFragment fragment, @NotNull FragmentsCollector collector) throws FilesTooBigForDiffException {
       if (!fragment.isChange()) {
         collector.add(fragment);
         return;
       }
-      String text1 = fragment.getText1();
-      String text2 = fragment.getText2();
+      DiffString text1 = fragment.getText1();
+      DiffString text2 = fragment.getText2();
       while (StringUtil.startsWithChar(text1, '\n') || StringUtil.startsWithChar(text2, '\n')) {
-        String newLine1 = null;
-        String newLine2 = null;
+        DiffString newLine1 = null;
+        DiffString newLine2 = null;
         if (StringUtil.startsWithChar(text1, '\n')) {
-          newLine1 = "\n";
+          newLine1 = DiffString.create("\n");
           text1 = text1.substring(1);
         }
         if (StringUtil.startsWithChar(text2, '\n')) {
-          newLine2 = "\n";
+          newLine2 = DiffString.create("\n");
           text2 = text2.substring(1);
         }
         collector.add(new DiffFragment(newLine1, newLine2));
       }
-      String spaces1 = leadingSpaces(text1);
-      String spaces2 = leadingSpaces(text2);
+      DiffString spaces1 = text1.getLeadingSpaces();
+      DiffString spaces2 = text2.getLeadingSpaces();
       if (spaces1.isEmpty() && spaces2.isEmpty()) {
         DiffFragment trailing = myComparisonPolicy.createFragment(text1, text2);
         collector.add(trailing);
         return;
       }
       collector.addAll(myDiffPolicy.buildFragments(spaces1, spaces2));
-      DiffFragment textFragment = myComparisonPolicy.createFragment(text1.substring(spaces1.length(), text1.length()),
-                                                          text2.substring(spaces2.length(), text2.length()));
+      DiffFragment textFragment = myComparisonPolicy
+        .createFragment(text1.substring(spaces1.length(), text1.length()), text2.substring(spaces2.length(), text2.length()));
       collector.add(textFragment);
     }
 
-    private String leadingSpaces(String text) {
-      int i = 0;
-      while (i < text.length() && text.charAt(i) == ' ') i++;
-      return text.substring(0, i);
-    }
-
     @Override
     public DiffFragment[] correct(DiffFragment[] fragments) throws FilesTooBigForDiffException {
       FragmentsCollector collector = new FragmentsCollector();
@@ -125,7 +123,7 @@
   }
 
   interface FragmentProcessor<Collector> {
-    void process(DiffFragment fragment, Collector collector) throws FilesTooBigForDiffException;
+    void process(@NotNull DiffFragment fragment, @NotNull Collector collector) throws FilesTooBigForDiffException;
   }
 
   class BaseFragmentRunner<ActualRunner extends BaseFragmentRunner> {
@@ -158,8 +156,7 @@
       }
     }
 
-    // todo think where
-    public static int getTextLength(String text) {
+    public static int getTextLength(DiffString text) {
       return text != null ? text.length() : 0;
     }
 
@@ -224,7 +221,7 @@
     }
 
     @Override
-    public void process(DiffFragment fragment, FragmentBuffer buffer) {
+    public void process(@NotNull DiffFragment fragment, @NotNull FragmentBuffer buffer) {
       if (fragment.isOneSide()) buffer.markIfNone(DEFAULT_MODE);
       else buffer.add(fragment);
     }
@@ -243,7 +240,7 @@
     }
 
     @Override
-    public void process(DiffFragment fragment, FragmentBuffer buffer) {
+    public void process(@NotNull DiffFragment fragment, @NotNull FragmentBuffer buffer) {
       if (fragment.isEqual()) buffer.markIfNone(EQUAL_MODE);
       else if (ComparisonPolicy.TRIM_SPACE.isEqual(fragment)) buffer.markIfNone(FORMATTING_MODE);
       else  buffer.add(fragment);
@@ -273,10 +270,10 @@
     }
 
     @Override
-    public void process(DiffFragment fragment, FragmentBuffer buffer) {
+    public void process(@NotNull DiffFragment fragment, @NotNull FragmentBuffer buffer) {
       if (fragment.isEqual()) buffer.add(fragment);
       else if (fragment.isOneSide()) {
-        String text = FragmentSide.chooseSide(fragment).getText(fragment);
+        DiffString text = FragmentSide.chooseSide(fragment).getText(fragment);
         if (StringUtil.endsWithChar(text, '\n'))
           buffer.add(fragment);
         else
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/DiffPolicy.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/DiffPolicy.java
index 21cfc3d..4547252 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/processing/DiffPolicy.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/processing/DiffPolicy.java
@@ -15,13 +15,20 @@
  */
 package com.intellij.openapi.diff.impl.processing;
 
-import com.intellij.openapi.diff.LineTokenizer;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
 import com.intellij.util.diff.FilesTooBigForDiffException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
 
 public interface DiffPolicy {
-  DiffFragment[] buildFragments(String text1, String text2) throws FilesTooBigForDiffException;
+  @NotNull
+  DiffFragment[] buildFragments(@NotNull DiffString text1, @NotNull DiffString text2) throws FilesTooBigForDiffException;
+
+  @NotNull
+  @TestOnly
+  DiffFragment[] buildFragments(@NotNull String text1, @NotNull String text2) throws FilesTooBigForDiffException;
 
   DiffPolicy LINES_WO_FORMATTING = new LineBlocks(ComparisonPolicy.IGNORE_SPACE);
   DiffPolicy DEFAULT_LINES = new LineBlocks(ComparisonPolicy.DEFAULT);
@@ -33,10 +40,17 @@
       myComparisonPolicy = comparisonPolicy;
     }
 
+    @NotNull
+    @TestOnly
+    public DiffFragment[] buildFragments(@NotNull String text1, @NotNull String text2) throws FilesTooBigForDiffException {
+      return buildFragments(DiffString.create(text1), DiffString.create(text2));
+    }
+
+    @NotNull
     @Override
-    public DiffFragment[] buildFragments(String text1, String text2) throws FilesTooBigForDiffException {
-      String[] strings1 = new LineTokenizer(text1).execute();
-      String[] strings2 = new LineTokenizer(text2).execute();
+    public DiffFragment[] buildFragments(@NotNull DiffString text1, @NotNull DiffString text2) throws FilesTooBigForDiffException {
+      DiffString[] strings1 = text1.tokenize();
+      DiffString[] strings2 = text2.tokenize();
       return myComparisonPolicy.buildDiffFragmentsFromLines(strings1, strings2);
     }
 
@@ -49,13 +63,20 @@
       myComparisonPolicy = comparisonPolicy;
     }
 
+    @NotNull
+    @TestOnly
+    public DiffFragment[] buildFragments(@NotNull String text1, @NotNull String text2) throws FilesTooBigForDiffException {
+      return buildFragments(DiffString.create(text1), DiffString.create(text2));
+    }
+
+    @NotNull
     @Override
-    public DiffFragment[] buildFragments(String text1, String text2) throws FilesTooBigForDiffException {
+    public DiffFragment[] buildFragments(@NotNull DiffString text1, @NotNull DiffString text2) throws FilesTooBigForDiffException {
       return myComparisonPolicy.buildFragments(splitByChar(text1), splitByChar(text2));
     }
 
-    private String[] splitByChar(String text) {
-      String[] result = new String[text.length()];
+    private static DiffString[] splitByChar(@NotNull DiffString text) {
+      DiffString[] result = new DiffString[text.length()];
       for (int i = 0; i < result.length; i++) {
         result[i] = text.substring(i, i + 1);
       }
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/Formatting.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/Formatting.java
index 8a520f2..a4eaf35 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/processing/Formatting.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/processing/Formatting.java
@@ -15,10 +15,18 @@
  */
 package com.intellij.openapi.diff.impl.processing;
 
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
 
 public class Formatting extends Word {
-  public Formatting(String text, TextRange range) {
+  @TestOnly
+  public Formatting(@NotNull String baseText, @NotNull TextRange range) {
+    this(DiffString.create(baseText), range);
+  }
+
+  public Formatting(@NotNull DiffString text, @NotNull TextRange range) {
     super(text, range);
   }
 
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/LineFragmentsCollector.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/LineFragmentsCollector.java
index fd8a22d..7534286 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/processing/LineFragmentsCollector.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/processing/LineFragmentsCollector.java
@@ -15,11 +15,14 @@
  */
 package com.intellij.openapi.diff.impl.processing;
 
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.fragments.LineFragment;
 import com.intellij.openapi.diff.impl.util.TextDiffTypeEnum;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 
@@ -30,14 +33,14 @@
   private int myOffset1 = 0;
   private int myOffset2 = 0;
 
-  private LineFragment addFragment(TextDiffTypeEnum type, String text1, String text2) {
+  @NotNull
+  private LineFragment addFragment(@Nullable TextDiffTypeEnum type, @Nullable DiffString text1, @Nullable DiffString text2) {
     int lines1 = countLines(text1);
     int lines2 = countLines(text2);
     int endOffset1 = myOffset1 + getLength(text1);
     int endOffset2 = myOffset2 + getLength(text2);
-    LineFragment lineFragment = new LineFragment(myLine1, lines1, myLine2, lines2, type,
-                              new TextRange(myOffset1, endOffset1),
-                              new TextRange(myOffset2, endOffset2));
+    LineFragment lineFragment =
+      new LineFragment(myLine1, lines1, myLine2, lines2, type, new TextRange(myOffset1, endOffset1), new TextRange(myOffset2, endOffset2));
     myLine1 += lines1;
     myLine2 += lines2;
     myOffset1 = endOffset1;
@@ -46,18 +49,19 @@
     return lineFragment;
   }
 
-  public LineFragment addDiffFragment(DiffFragment fragment) {
+  @NotNull
+  public LineFragment addDiffFragment(@NotNull DiffFragment fragment) {
     return addFragment(getType(fragment), fragment.getText1(), fragment.getText2());
   }
 
-  static int getLength(String text) {
+  static int getLength(@Nullable DiffString text) {
     return text == null ? 0 : text.length();
   }
 
-  private static int countLines(String text) {
+  private static int countLines(@Nullable DiffString text) {
     if (text == null || text.isEmpty()) return 0;
     int count = StringUtil.countNewLines(text);
-    if (text.charAt(text.length()-1) != '\n') count++;
+    if (text.charAt(text.length() - 1) != '\n') count++;
     return count;
   }
 
@@ -65,7 +69,8 @@
     return myLineFragments;
   }
 
-  static TextDiffTypeEnum getType(DiffFragment fragment) {
+  @Nullable
+  static TextDiffTypeEnum getType(@NotNull DiffFragment fragment) {
     TextDiffTypeEnum type;
     if (fragment.getText1() == null) type = TextDiffTypeEnum.INSERT;
     else if (fragment.getText2() == null) type = TextDiffTypeEnum.DELETED;
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/UniteSameType.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/UniteSameType.java
index ee166ce..bf21f10 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/processing/UniteSameType.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/processing/UniteSameType.java
@@ -16,10 +16,12 @@
 package com.intellij.openapi.diff.impl.processing;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
 import com.intellij.openapi.diff.impl.highlighting.Util;
 import com.intellij.util.diff.FilesTooBigForDiffException;
+import org.jetbrains.annotations.NotNull;
 
 class UniteSameType implements DiffCorrection {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.processing.UniteSameType");
@@ -29,7 +31,8 @@
     return unitSameTypes(covertSequentialOneSideToChange(unitSameTypes(fragments)));
   }
 
-  private DiffFragment[] unitSameTypes(DiffFragment[] fragments) {
+  @NotNull
+  private static DiffFragment[] unitSameTypes(@NotNull DiffFragment[] fragments) {
     if (fragments.length < 2) return fragments;
     DiffCorrection.FragmentsCollector collector = new DiffCorrection.FragmentsCollector();
     DiffFragment previous = fragments[0];
@@ -47,7 +50,8 @@
     return collector.toArray();
   }
 
-  private DiffFragment[] covertSequentialOneSideToChange(DiffFragment[] fragments) {
+  @NotNull
+  private static DiffFragment[] covertSequentialOneSideToChange(@NotNull DiffFragment[] fragments) {
     if (fragments.length < 2) return fragments;
     DiffCorrection.FragmentsCollector collector = new DiffCorrection.FragmentsCollector();
 //    DiffFragment previous = fragments[0];
@@ -58,9 +62,10 @@
         if (previous == null) previous = fragment;
         else {
           FragmentSide side = FragmentSide.chooseSide(fragment);
-          String previousText = side.getText(previous);
-          if (previousText == null) previousText = "";
-          previous = side.createFragment(previousText + side.getText(fragment), side.getOtherText(previous), true);
+          DiffString previousText = side.getText(previous);
+          if (previousText == null) previousText = DiffString.EMPTY;
+          previous = side.createFragment(DiffString.concatenateNullable(previousText, side.getText(fragment)),
+                                         side.getOtherText(previous), true);
         }
       } else {
         if (previous != null) collector.add(previous);
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/Word.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/Word.java
index 3279fc4..d9d67dc 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/processing/Word.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/processing/Word.java
@@ -16,22 +16,32 @@
 package com.intellij.openapi.diff.impl.processing;
 
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
 
 public class Word {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.processing.Word");
-  private final String myText;
-  private final TextRange myRange;
+  @NotNull private final DiffString myBaseText;
+  @NotNull private final TextRange myRange;
+  @NotNull private final DiffString myText;
 
-  public Word(String text, TextRange range) {
-    myText = text;
+  @TestOnly
+  public Word(@NotNull String baseText, @NotNull TextRange range) {
+    this(DiffString.create(baseText), range);
+  }
+
+  public Word(@NotNull DiffString baseText, @NotNull TextRange range) {
+    myBaseText = baseText;
     myRange = range;
+    myText = myBaseText.substring(myRange.getStartOffset(), myRange.getEndOffset());
     LOG.assertTrue(myRange.getStartOffset() >= 0);
     LOG.assertTrue(myRange.getEndOffset() >= myRange.getStartOffset(), myRange);
   }
 
   public int hashCode() {
-    return getText().hashCode();
+    return myText.hashCode();
   }
 
   public boolean equals(Object obj) {
@@ -40,15 +50,17 @@
     return getText().equals(other.getText());
   }
 
-  public String getText() {
-    return myRange.substring(myText);
+  @NotNull
+  public DiffString getText() {
+    return myText;
   }
 
-  public String getPrefix(int fromPosition) {
-    LOG.assertTrue(fromPosition >= 0, "" + fromPosition);
+  @NotNull
+  public DiffString getPrefix(int fromPosition) {
+    LOG.assertTrue(fromPosition >= 0, fromPosition);
     int wordStart = myRange.getStartOffset();
-    LOG.assertTrue(fromPosition <= wordStart, "" + fromPosition + " " + wordStart);
-    return myText.substring(fromPosition, wordStart);
+    LOG.assertTrue(fromPosition <= wordStart, fromPosition + " " + wordStart);
+    return myBaseText.substring(fromPosition, wordStart);
   }
 
   public int getEnd() {
@@ -60,7 +72,7 @@
   }
 
   public String toString() {
-    return getText();
+    return myText.toString();
   }
 
   public boolean isWhitespace() {
@@ -70,10 +82,10 @@
   public boolean atEndOfLine() {
     int start = myRange.getStartOffset();
     if (start == 0) return true;
-    if (myText.charAt(start - 1) == '\n') return true;
+    if (myBaseText.charAt(start - 1) == '\n') return true;
     int end = myRange.getEndOffset();
-    if (end == myText.length()) return true;
-    if (myText.charAt(end) == '\n') return true;
+    if (end == myBaseText.length()) return true;
+    if (myBaseText.charAt(end) == '\n') return true;
     return false;
   }
 }
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/string/DiffString.java b/platform/util/src/com/intellij/openapi/diff/impl/string/DiffString.java
new file mode 100644
index 0000000..76aa434
--- /dev/null
+++ b/platform/util/src/com/intellij/openapi/diff/impl/string/DiffString.java
@@ -0,0 +1,420 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff.impl.string;
+
+import com.intellij.openapi.diff.LineTokenizerBase;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class DiffString implements CharSequence {
+  @NotNull public static final DiffString EMPTY = new DiffString(new char[0], 0, 0);
+
+  @NotNull private final char[] myData;
+  private final int myStart;
+  private final int myLength;
+  private int myHash;
+
+  @Nullable
+  public static DiffString createNullable(@Nullable String string) {
+    if (string == null) return null;
+    return create(string);
+  }
+
+  @NotNull
+  public static DiffString create(@NotNull String string) {
+    if (string.isEmpty()) return EMPTY;
+    return create(string.toCharArray());
+  }
+
+  @NotNull
+  static DiffString create(@NotNull char[] data) {
+    return create(data, 0, data.length);
+  }
+
+  @NotNull
+  static DiffString create(@NotNull char[] data, int start, int length) {
+    if (length == 0) return EMPTY;
+    checkBounds(start, length, data.length);
+    return new DiffString(data, start, length);
+  }
+
+  private DiffString(@NotNull char[] data, int start, int length) {
+    myData = data;
+    myStart = start;
+    myLength = length;
+  }
+
+  @Override
+  public int length() {
+    return myLength;
+  }
+
+  public boolean isEmpty() {
+    return myLength == 0;
+  }
+
+  @Override
+  public char charAt(int index) {
+    if (index < 0 || index >= myLength) {
+      throw new StringIndexOutOfBoundsException(index);
+    }
+    return data(index);
+  }
+
+  public char data(int index) {
+    return myData[myStart + index];
+  }
+
+  @NotNull
+  public DiffString substring(int start) {
+    return substring(start, myLength);
+  }
+
+  @NotNull
+  public DiffString substring(int start, int end) {
+    if (start == 0 && end == myLength) return this;
+    checkBounds(start, end - start, myLength);
+    return create(myData, myStart + start, end - start);
+  }
+
+  @Override
+  public DiffString subSequence(int start, int end) {
+    return substring(start, end);
+  }
+
+  @NotNull
+  @Override
+  public String toString() {
+    return new String(myData, myStart, myLength);
+  }
+
+  @NotNull
+  public DiffString copy() {
+    return create(Arrays.copyOfRange(myData, myStart, myStart + myLength));
+  }
+
+  public void copyData(@NotNull char[] dst, int start) {
+    checkBounds(start, myLength, dst.length);
+    System.arraycopy(myData, myStart, dst, start, myLength);
+  }
+
+  @Override
+  public boolean equals(@Nullable Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    DiffString that = (DiffString)o;
+
+    if (myLength != that.myLength) return false;
+    if (hashCode() != that.hashCode()) return false;
+    for (int i = 0; i < myLength; i++) {
+      if (data(i) != that.data(i)) return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int h = myHash;
+    if (h == 0) {
+      h = StringUtil.stringHashCode(myData, myStart, myStart + myLength);
+      if (h == 0) h = 1;
+      myHash = h;
+    }
+    return h;
+  }
+
+  @Nullable
+  public static DiffString concatenateNullable(@Nullable DiffString s1, @Nullable DiffString s2) {
+    if (s1 == null || s2 == null) {
+      if (s1 != null) return s1;
+      if (s2 != null) return s2;
+      return null;
+    }
+
+    return concatenate(s1, s2);
+  }
+
+  @NotNull
+  public static DiffString concatenate(@NotNull DiffString s1, @NotNull DiffString s2) {
+    if (s1.isEmpty()) return s2;
+    if (s2.isEmpty()) return s1;
+
+    if (s1.myData == s2.myData && s1.myStart + s1.myLength == s2.myStart) {
+      return create(s1.myData, s1.myStart, s1.myLength + s2.myLength);
+    }
+
+    char[] data = new char[s1.myLength + s2.myLength];
+    System.arraycopy(s1.myData, s1.myStart, data, 0, s1.myLength);
+    System.arraycopy(s2.myData, s2.myStart, data, s1.myLength, s2.myLength);
+    return create(data);
+  }
+
+  public static boolean canInplaceConcatenate(@NotNull DiffString s1, @NotNull DiffString s2) {
+    if (s1.isEmpty()) return true;
+    if (s2.isEmpty()) return true;
+
+    if (s1.myData == s2.myData && s1.myStart + s1.myLength == s2.myStart) {
+      return true;
+    }
+
+    return false;
+  }
+
+  @NotNull
+  public static DiffString concatenateCopying(@NotNull DiffString[] strings) {
+    return concatenateCopying(strings, 0, strings.length);
+  }
+
+  @NotNull
+  public static DiffString concatenateCopying(@NotNull DiffString[] strings, int start, int length) {
+    checkBounds(start, length, strings.length);
+
+    int len = 0;
+    for (int i = 0; i < length; i++) {
+      DiffString string = strings[start + i];
+      len += string == null ? 0 : string.myLength;
+    }
+
+    if (len == 0) return EMPTY;
+
+    char[] data = new char[len];
+    int index = 0;
+    for (int i = 0; i < length; i++) {
+      DiffString string = strings[start + i];
+      if (string == null || string.isEmpty()) continue;
+      System.arraycopy(string.myData, string.myStart, data, index, string.myLength);
+      index += string.myLength;
+    }
+    return create(data);
+  }
+
+  @NotNull
+  public static DiffString concatenate(@NotNull DiffString s, char c) {
+    if (s.myStart + s.myLength < s.myData.length && s.data(s.myLength) == c) {
+      return create(s.myData, s.myStart, s.myLength + 1);
+    }
+
+    char[] data = new char[s.myLength + 1];
+    System.arraycopy(s.myData, s.myStart, data, 0, s.myLength);
+    data[s.myLength] = c;
+    return create(data);
+  }
+
+  @NotNull
+  public static DiffString concatenate(char c, @NotNull DiffString s) {
+    if (s.myStart > 0 && s.data(-1) == c) {
+      return create(s.myData, s.myStart - 1, s.myLength + 1);
+    }
+
+    char[] data = new char[s.myLength + 1];
+    System.arraycopy(s.myData, s.myStart, data, 1, s.myLength);
+    data[0] = c;
+    return create(data);
+  }
+
+  @NotNull
+  public static DiffString concatenate(@NotNull DiffString[] strings) {
+    return concatenate(strings, 0, strings.length);
+  }
+
+  @NotNull
+  public static DiffString concatenate(@NotNull DiffString[] strings, int start, int length) {
+    checkBounds(start, length, strings.length);
+
+    char[] data = null;
+    int startIndex = 0;
+    int endIndex = 0;
+
+    boolean linearized = true;
+    for (int i = 0; i < length; i++) {
+      DiffString string = strings[start + i];
+      if (string == null || string.isEmpty()) continue;
+      if (data == null) {
+        data = string.myData;
+        startIndex = string.myStart;
+        endIndex = string.myStart + string.myLength;
+        continue;
+      }
+      if (data != string.myData || string.myStart != endIndex) {
+        linearized = false;
+        break;
+      }
+      endIndex += string.myLength;
+    }
+
+    if (linearized) {
+      if (data == null) return EMPTY;
+      return create(data, startIndex, endIndex - startIndex);
+    }
+
+    return concatenateCopying(strings, start, length);
+  }
+
+  @NotNull
+  public DiffString append(char c) {
+    return concatenate(this, c);
+  }
+
+  @NotNull
+  public DiffString preappend(char c) {
+    return concatenate(c, this);
+  }
+
+  public static boolean isWhiteSpace(char c) {
+    return StringUtil.isWhiteSpace(c);
+  }
+
+  public boolean isEmptyOrSpaces() {
+    if (isEmpty()) return true;
+
+    for (int i = 0; i < myLength; i++) {
+      if (!isWhiteSpace(data(i))) return false;
+    }
+    return true;
+  }
+
+  @NotNull
+  public DiffString trim() {
+    int start = 0;
+    int end = myLength;
+
+    while (start < end && isWhiteSpace(data(start))) start++;
+    while (end > start && isWhiteSpace(data(end - 1))) end--;
+
+    return substring(start, end);
+  }
+
+  @NotNull
+  public DiffString trimLeading() {
+    int i = 0;
+
+    while (i < myLength && isWhiteSpace(data(i))) i++;
+
+    return substring(i, myLength);
+  }
+
+  @NotNull
+  public DiffString trimTrailing() {
+    int end = myLength;
+
+    while (end > 0 && isWhiteSpace(data(end - 1))) end--;
+
+    return substring(0, end);
+  }
+
+  @NotNull
+  public DiffString getLeadingSpaces() {
+    int i = 0;
+
+    while (i < myLength && data(i) == ' ') i++;
+
+    return substring(0, i);
+  }
+
+  @NotNull
+  public DiffString skipSpaces() {
+    DiffString s = trim();
+    int count = 0;
+    for (int i = 0; i < s.myLength; i++) {
+      if (isWhiteSpace(s.data(i))) count++;
+    }
+    if (count == 0) return s;
+
+    char[] data = new char[s.myLength - count];
+    int index = 0;
+    for (int i = 0; i < s.myLength; i++) {
+      if (isWhiteSpace(s.data(i))) continue;
+      data[index] = s.data(i);
+      index++;
+    }
+    return create(data);
+  }
+
+  public int indexOf(char c) {
+    return StringUtil.indexOf(this, c);
+  }
+
+  public boolean endsWith(char c) {
+    if (isEmpty()) return false;
+    return data(myLength - 1) == c;
+  }
+
+  public static void checkBounds(int start, int length, int maxLength) {
+    if (start < 0) {
+      throw new StringIndexOutOfBoundsException(start);
+    }
+    if (length < 0) {
+      throw new StringIndexOutOfBoundsException(length);
+    }
+    if (start + length > maxLength) {
+      throw new StringIndexOutOfBoundsException(start + length);
+    }
+  }
+
+  @NotNull
+  public DiffString[] tokenize() {
+    return new LineTokenizer(this).execute();
+  }
+
+  public static class LineTokenizer extends LineTokenizerBase<DiffString> {
+    @NotNull private final DiffString myText;
+
+    public LineTokenizer(@NotNull DiffString text) {
+      myText = text;
+    }
+
+    @NotNull
+    public DiffString[] execute() {
+      ArrayList<DiffString> lines = new ArrayList<DiffString>();
+      doExecute(lines);
+      return ContainerUtil.toArray(lines, new DiffString[lines.size()]);
+    }
+
+    @Override
+    protected void addLine(List<DiffString> lines, int start, int end, boolean appendNewLine) {
+      if (appendNewLine) {
+        lines.add(myText.substring(start, end).append('\n'));
+      }
+      else {
+        lines.add(myText.substring(start, end));
+      }
+    }
+
+    @Override
+    protected char charAt(int index) {
+      return myText.data(index);
+    }
+
+    @Override
+    protected int length() {
+      return myText.length();
+    }
+
+    @NotNull
+    @Override
+    protected String substring(int start, int end) {
+      return myText.substring(start, end).toString();
+    }
+  }
+}
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/string/DiffStringBuilder.java b/platform/util/src/com/intellij/openapi/diff/impl/string/DiffStringBuilder.java
new file mode 100644
index 0000000..f1a700f
--- /dev/null
+++ b/platform/util/src/com/intellij/openapi/diff/impl/string/DiffStringBuilder.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff.impl.string;
+
+import com.intellij.openapi.diff.impl.string.DiffString;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+
+public class DiffStringBuilder implements CharSequence {
+  @NotNull private char[] myData;
+  private int myLength;
+
+  public DiffStringBuilder() {
+    this(16);
+  }
+
+  public DiffStringBuilder(int len) {
+    myData = new char[len];
+    myLength = 0;
+  }
+
+  @Override
+  public int length() {
+    return myLength;
+  }
+
+  @Override
+  public char charAt(int index) {
+    if (index < 0 || index >= myLength) {
+      throw new StringIndexOutOfBoundsException(index);
+    }
+    return myData[index];
+  }
+
+  @Override
+  @NotNull
+  public CharSequence subSequence(int start, int end) {
+    DiffString.checkBounds(start, end, myLength);
+    return DiffString.create(myData, start, end - start);
+  }
+
+  @NotNull
+  public DiffString toDiffString() {
+    return DiffString.create(myData, 0, myLength);
+  }
+
+  @Override
+  @NotNull
+  public String toString() {
+    return toDiffString().toString();
+  }
+
+  private void ensureCapacityInternal(int neededCapacity) {
+    if (neededCapacity > myData.length) {
+      int newCapacity = myData.length;
+      while (newCapacity < neededCapacity) newCapacity *= 2;
+
+      myData = Arrays.copyOf(myData, newCapacity);
+    }
+  }
+
+  public void append(@NotNull DiffString s) {
+    if (s.isEmpty()) return;
+    ensureCapacityInternal(myLength + s.length());
+    s.copyData(myData, myLength);
+    myLength += s.length();
+  }
+}
diff --git a/platform/util/src/com/intellij/openapi/util/JDOMExternalizer.java b/platform/util/src/com/intellij/openapi/util/JDOMExternalizer.java
index 72dc236..909c44d 100644
--- a/platform/util/src/com/intellij/openapi/util/JDOMExternalizer.java
+++ b/platform/util/src/com/intellij/openapi/util/JDOMExternalizer.java
@@ -19,6 +19,7 @@
 import com.intellij.util.ArrayUtil;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.*;
@@ -104,4 +105,15 @@
       }
     }
   }
+
+  public 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;
+  }
 }
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/openapi/util/Key.java b/platform/util/src/com/intellij/openapi/util/Key.java
index 949cb3e..09ef129 100644
--- a/platform/util/src/com/intellij/openapi/util/Key.java
+++ b/platform/util/src/com/intellij/openapi/util/Key.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.
@@ -42,6 +42,7 @@
     allKeys.put(myIndex, this);
   }
 
+  // made final because many classes depend on one-to-one key index <-> key instance relationship. See e.g. UserDataHolderBase
   public final int hashCode() {
     return myIndex;
   }
diff --git a/platform/util/src/com/intellij/util/LocalTimeCounter.java b/platform/util/src/com/intellij/util/LocalTimeCounter.java
index 1cfbdb7..41b09b7 100644
--- a/platform/util/src/com/intellij/util/LocalTimeCounter.java
+++ b/platform/util/src/com/intellij/util/LocalTimeCounter.java
@@ -18,12 +18,14 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 public class LocalTimeCounter {
+  /**
+   * VirtualFile.modificationStamp is kept modulo this mask, and is compared with other stamps. Let's avoid accidental stamp inequalities 
+   * by normalizing all of them. 
+   */
+  public static final int TIME_MASK = 0x00ffffff;
   private static final AtomicLong ourCurrentTime = new AtomicLong();
 
-  private LocalTimeCounter() {
-  }
-
   public static long currentTime() {
-    return ourCurrentTime.incrementAndGet();
+    return TIME_MASK & (int)ourCurrentTime.incrementAndGet();
   }
 }
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/util/diff/PatienceIntLCS.java b/platform/util/src/com/intellij/util/diff/PatienceIntLCS.java
index 5acb827..f20353e 100644
--- a/platform/util/src/com/intellij/util/diff/PatienceIntLCS.java
+++ b/platform/util/src/com/intellij/util/diff/PatienceIntLCS.java
@@ -120,7 +120,7 @@
   }
 
   private int matchForward(int offset1, int offset2) {
-    final int size = Math.min(myCount1 - offset1, myCount2 - offset2);
+    final int size = Math.min(myCount1 + myStart1 - offset1, myCount2 + myStart2 - offset2);
     int idx = 0;
     for (int i = 0; i < size; i++) {
       if (!(myFirst[offset1 + i] == mySecond[offset2 + i])) break;
diff --git a/platform/util/src/com/intellij/util/io/DataExternalizer.java b/platform/util/src/com/intellij/util/io/DataExternalizer.java
index 4445429..f252424 100644
--- a/platform/util/src/com/intellij/util/io/DataExternalizer.java
+++ b/platform/util/src/com/intellij/util/io/DataExternalizer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -15,12 +15,14 @@
  */
 package com.intellij.util.io;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
 
 public interface DataExternalizer<T> {
-  void save(DataOutput out, T value) throws IOException;
+  void save(@NotNull DataOutput out, T value) throws IOException;
 
-  T read(DataInput in) throws IOException;
+  T read(@NotNull DataInput in) throws IOException;
 }
diff --git a/platform/util/src/com/intellij/util/io/EnumeratorStringDescriptor.java b/platform/util/src/com/intellij/util/io/EnumeratorStringDescriptor.java
index 1621cf3..a662aae 100644
--- a/platform/util/src/com/intellij/util/io/EnumeratorStringDescriptor.java
+++ b/platform/util/src/com/intellij/util/io/EnumeratorStringDescriptor.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.
@@ -37,13 +37,13 @@
   }
 
   @Override
-  public void save(final DataOutput storage, @NotNull final String value) throws IOException {
+  public void save(@NotNull final DataOutput storage, @NotNull final String value) throws IOException {
     final byte[] buffer = IOUtil.allocReadWriteUTFBuffer();
     IOUtil.writeUTFFast(buffer, storage, value);
   }
 
   @Override
-  public String read(final DataInput storage) throws IOException {
+  public String read(@NotNull final DataInput storage) throws IOException {
     final byte[] buffer = IOUtil.allocReadWriteUTFBuffer();
     return IOUtil.readUTFFast(buffer, storage);
   }
diff --git a/platform/util/src/com/intellij/util/io/ExternalIntegerKeyDescriptor.java b/platform/util/src/com/intellij/util/io/ExternalIntegerKeyDescriptor.java
index 009581e..cb3e146 100644
--- a/platform/util/src/com/intellij/util/io/ExternalIntegerKeyDescriptor.java
+++ b/platform/util/src/com/intellij/util/io/ExternalIntegerKeyDescriptor.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.
@@ -19,6 +19,8 @@
  */
 package com.intellij.util.io;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
@@ -35,12 +37,12 @@
   }
 
   @Override
-  public void save(final DataOutput out, final Integer value) throws IOException {
+  public void save(@NotNull final DataOutput out, final Integer value) throws IOException {
     DataInputOutputUtil.writeINT(out, value.intValue());
   }
 
   @Override
-  public Integer read(final DataInput in) throws IOException {
+  public Integer read(@NotNull final DataInput in) throws IOException {
     return DataInputOutputUtil.readINT(in);
   }
 }
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/util/io/InlineKeyDescriptor.java b/platform/util/src/com/intellij/util/io/InlineKeyDescriptor.java
index 8cf030a..d64df97 100644
--- a/platform/util/src/com/intellij/util/io/InlineKeyDescriptor.java
+++ b/platform/util/src/com/intellij/util/io/InlineKeyDescriptor.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.
@@ -19,6 +19,8 @@
  */
 package com.intellij.util.io;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
@@ -41,14 +43,14 @@
   }
 
   @Override
-  public final void save(DataOutput out, T value) throws IOException {
+  public final void save(@NotNull DataOutput out, T value) throws IOException {
     int v = toInt(value);
     if (myCompactFormat) DataInputOutputUtil.writeINT(out, v);
     else out.writeInt(v);
   }
 
   @Override
-  public final T read(DataInput in) throws IOException {
+  public final T read(@NotNull DataInput in) throws IOException {
     int n;
     if (myCompactFormat) n = DataInputOutputUtil.readINT(in);
     else n = in.readInt();
diff --git a/platform/util/src/com/intellij/util/io/MappedFileInputStream.java b/platform/util/src/com/intellij/util/io/MappedFileInputStream.java
index c67c816..10a57dc 100644
--- a/platform/util/src/com/intellij/util/io/MappedFileInputStream.java
+++ b/platform/util/src/com/intellij/util/io/MappedFileInputStream.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.
@@ -25,24 +25,24 @@
 import java.io.InputStream;
 
 public class MappedFileInputStream extends InputStream {
-  private ResizeableMappedFile raf;
+  private final ResizeableMappedFile raf;
   private int cur;
   private long limit;
 
-  public MappedFileInputStream(final ResizeableMappedFile raf, final long pos, final long limit) {
+  public MappedFileInputStream(@NotNull ResizeableMappedFile raf, final long pos, final long limit) {
     this.raf = raf;
     setup(pos, limit);
   }
 
+  public MappedFileInputStream(@NotNull ResizeableMappedFile raf, final long pos) throws IOException {
+    this(raf, pos, raf.length());
+  }
+
   public void setup(final long pos, final long limit) {
     this.cur = (int)pos;
     this.limit = limit;
   }
 
-  public MappedFileInputStream(final ResizeableMappedFile raf, final long pos) throws IOException {
-    this(raf, pos, raf.length());
-  }
-
   @Override
   public int available()
   {
@@ -67,7 +67,7 @@
   }
 
   @Override
-  public int read( @NotNull byte[] b, int offset, int length ) throws IOException
+  public int read(@NotNull byte[] b, int offset, int length ) throws IOException
   {
       //only allow a read of the amount available.
       if( length > available() )
diff --git a/platform/util/src/com/intellij/util/io/NullableDataExternalizer.java b/platform/util/src/com/intellij/util/io/NullableDataExternalizer.java
index 7f8bba8..897fa7d 100644
--- a/platform/util/src/com/intellij/util/io/NullableDataExternalizer.java
+++ b/platform/util/src/com/intellij/util/io/NullableDataExternalizer.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.
@@ -15,6 +15,7 @@
  */
 package com.intellij.util.io;
 
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.DataOutput;
@@ -32,7 +33,7 @@
   }
 
   @Override
-  public void save(DataOutput out, T value) throws IOException {
+  public void save(@NotNull DataOutput out, T value) throws IOException {
     if (value == null) {
       out.writeBoolean(false);
     } else {
@@ -43,7 +44,7 @@
 
   @Override
   @Nullable
-  public T read(DataInput in) throws IOException {
+  public T read(@NotNull DataInput in) throws IOException {
     final boolean isDefined = in.readBoolean();
     if (isDefined) {
       return myNotNullExternalizer.read(in);
diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java
index 5cb7ad4..6903c6b 100644
--- a/platform/util/src/com/intellij/util/ui/UIUtil.java
+++ b/platform/util/src/com/intellij/util/ui/UIUtil.java
@@ -45,6 +45,7 @@
 import javax.swing.text.JTextComponent;
 import javax.swing.text.html.HTMLEditorKit;
 import javax.swing.text.html.StyleSheet;
+import javax.swing.undo.UndoManager;
 import java.awt.*;
 import java.awt.event.*;
 import java.awt.font.FontRenderContext;
@@ -1584,6 +1585,7 @@
     g.setComposite(X_RENDER_ACTIVE.getValue() ? AlphaComposite.SrcOver : AlphaComposite.Src);
   }
 
+  /** @see #pump() */
   @TestOnly
   public static void dispatchAllInvocationEvents() {
     assert SwingUtilities.isEventDispatchThread() : Thread.currentThread();
@@ -1603,6 +1605,7 @@
     }
   }
 
+  /** @see #dispatchAllInvocationEvents() */
   @TestOnly
   public static void pump() {
     assert !SwingUtilities.isEventDispatchThread();
@@ -2778,4 +2781,28 @@
     }
     return false;
   }
+
+  public static void addUndoRedoActions(JTextComponent textComponent) {
+    final UndoManager undoManager = new UndoManager();
+    textComponent.getDocument().addUndoableEditListener(undoManager);
+    textComponent.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, SystemInfo.isMac? InputEvent.META_MASK : InputEvent.CTRL_MASK), "undoKeystroke");
+    textComponent.getActionMap().put("undoKeystroke", new AbstractAction() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        if (undoManager.canUndo()) {
+          undoManager.undo();
+        }
+      }
+    });
+    textComponent.getInputMap().put(
+      KeyStroke.getKeyStroke(KeyEvent.VK_Z, (SystemInfo.isMac? InputEvent.META_MASK : InputEvent.CTRL_MASK) | InputEvent.SHIFT_MASK), "redoKeystroke");
+    textComponent.getActionMap().put("redoKeystroke", new AbstractAction() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+         if (undoManager.canRedo()) {
+           undoManager.redo();
+         }
+      }
+    });
+  }
 }
diff --git a/platform/util/src/com/intellij/util/xmlb/TextBinding.java b/platform/util/src/com/intellij/util/xmlb/TextBinding.java
index a195b3b..57cc3ef 100644
--- a/platform/util/src/com/intellij/util/xmlb/TextBinding.java
+++ b/platform/util/src/com/intellij/util/xmlb/TextBinding.java
@@ -32,6 +32,7 @@
   @Override
   public Object serialize(Object o, Object context, SerializationFilter filter) {
     final Object v = myAccessor.read(o);
+    if (v == null) return context;
     final Object node = myBinding.serialize(v, context, filter);
 
     return new Text(((Content)node).getValue());
diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
index d705888..7a147e0 100644
--- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
+++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
@@ -1029,6 +1029,31 @@
     }
   }
 
+  public static class ConversionFromTextToAttributeBean {
+    @Property(surroundWithTag = false)
+    public ConditionBean myConditionBean = new ConditionBean();
+  }
+  @Tag("condition")
+  public static class ConditionBean {
+    @Attribute("expression")
+    public String myNewCondition;
+    @Text
+    public String myOldCondition;
+  }
+
+  public void testConversionFromTextToAttribute() {
+    ConversionFromTextToAttributeBean bean = new ConversionFromTextToAttributeBean();
+    bean.myConditionBean.myOldCondition = "2+2";
+    doSerializerTest("<ConversionFromTextToAttributeBean>\n" +
+                     "  <condition>2+2</condition>\n" +
+                     "</ConversionFromTextToAttributeBean>", bean);
+
+    bean = new ConversionFromTextToAttributeBean();
+    bean.myConditionBean.myNewCondition = "2+2";
+    doSerializerTest("<ConversionFromTextToAttributeBean>\n" +
+                     "  <condition expression=\"2+2\" />\n" +
+                     "</ConversionFromTextToAttributeBean>", bean);
+  }
 
   public void testDeserializeInto() throws Exception {
     BeanWithPublicFields bean = new BeanWithPublicFields();
diff --git a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java
index 75918b5..9a78602 100644
--- a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java
+++ b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java
@@ -354,23 +354,31 @@
       PatchHunk hunk = new PatchHunk(startLineBefore-1, startLineBefore+linesBefore-1, startLineAfter-1, startLineAfter+linesAfter-1);
 
       PatchLine lastLine = null;
-      int numLines = linesBefore + linesAfter;
+      int before = 0;
+      int after = 0;
       while (iterator.hasNext()) {
         String hunkCurLine = iterator.next();
-        -- numLines;
         if (lastLine != null && hunkCurLine.startsWith(NO_NEWLINE_SIGNATURE)) {
           lastLine.setSuppressNewLine(true);
           continue;
         }
-        if (hunkCurLine.startsWith("--- ") && numLines == 0) {
-          iterator.previous();
-          break;
-        }
-        lastLine = parsePatchLine(hunkCurLine, 1);
+        lastLine = parsePatchLine(hunkCurLine, 1, before < linesBefore || after < linesAfter);
         if (lastLine == null) {
           iterator.previous();
           break;
         }
+        switch (lastLine.getType()) {
+          case CONTEXT:
+            before++;
+            after++;
+            break;
+          case ADD:
+            after++;
+            break;
+          case REMOVE:
+            before++;
+            break;
+        }
         hunk.addLine(lastLine);
       }
       return hunk;
@@ -389,11 +397,16 @@
 
     @Nullable
     private static PatchLine parsePatchLine(final String line, final int prefixLength) {
+      return parsePatchLine(line, prefixLength, true);
+    }
+
+    @Nullable
+    private static PatchLine parsePatchLine(final String line, final int prefixLength, boolean expectMeaningfulLines) {
       PatchLine.Type type;
-      if (line.startsWith("+")) {
+      if (line.startsWith("+") && expectMeaningfulLines) {
         type = PatchLine.Type.ADD;
       }
-      else if (line.startsWith("-")) {
+      else if (line.startsWith("-") && expectMeaningfulLines) {
         type = PatchLine.Type.REMOVE;
       }
       else if (line.startsWith(" ") || line.length() == 0) {
diff --git a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/TextPatchBuilder.java b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/TextPatchBuilder.java
index 7dc87ca..cbf110a 100644
--- a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/TextPatchBuilder.java
+++ b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/TextPatchBuilder.java
@@ -15,7 +15,7 @@
  */
 package com.intellij.openapi.diff.impl.patch;
 
-import com.intellij.openapi.diff.LineTokenizer;
+import com.intellij.openapi.diff.impl.string.DiffString;
 import com.intellij.openapi.diff.ex.DiffFragment;
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
 import com.intellij.openapi.diff.impl.fragments.LineFragment;
@@ -111,16 +111,16 @@
         continue;
       }
 
-      final String beforeContent = beforeRevision.getContentAsString();
+      final DiffString beforeContent = DiffString.createNullable(beforeRevision.getContentAsString());
       if (beforeContent == null) {
         throw new VcsException("Failed to fetch old content for changed file " + beforeRevision.getPath().getPath());
       }
-      final String afterContent = afterRevision.getContentAsString();
+      final DiffString afterContent = DiffString.createNullable(afterRevision.getContentAsString());
       if (afterContent == null) {
         throw new VcsException("Failed to fetch new content for changed file " + afterRevision.getPath().getPath());
       }
-      String[] beforeLines = tokenize(beforeContent);
-      String[] afterLines = tokenize(afterContent);
+      DiffString[] beforeLines = tokenize(beforeContent);
+      DiffString[] afterLines = tokenize(afterContent);
 
       DiffFragment[] woFormattingBlocks;
       DiffFragment[] step1lineFragments;
@@ -164,10 +164,10 @@
               checkCanceled();
               
               for(int i=contextStart1; i<fragment.getStartingLine1(); i++) {
-                addLineToHunk(hunk, beforeLines [i], PatchLine.Type.CONTEXT);
+                addLineToHunk(hunk, beforeLines[i], PatchLine.Type.CONTEXT);
               }
               for(int i=fragment.getStartingLine1(); i<fragment.getStartingLine1()+fragment.getModifiedLines1(); i++) {
-                addLineToHunk(hunk, beforeLines [i], PatchLine.Type.REMOVE);
+                addLineToHunk(hunk, beforeLines[i], PatchLine.Type.REMOVE);
               }
               for(int i=fragment.getStartingLine2(); i<fragment.getStartingLine2()+fragment.getModifiedLines2(); i++) {
                 addLineToHunk(hunk, afterLines[i], PatchLine.Type.ADD);
@@ -175,14 +175,14 @@
               contextStart1 = fragment.getStartingLine1()+fragment.getModifiedLines1();
             }
             for(int i=contextStart1; i<contextEnd1; i++) {
-              addLineToHunk(hunk, beforeLines [i], PatchLine.Type.CONTEXT);
+              addLineToHunk(hunk, beforeLines[i], PatchLine.Type.CONTEXT);
             }
           }
         }
 
         checkPathEndLine(patch, c.getAfter());
       } else if (! beforeRevision.getPath().equals(afterRevision.getPath())) {
-        final TextFilePatch movedPatch = buildMovedFile(myBasePath, beforeRevision, afterRevision, beforeLines);
+        final TextFilePatch movedPatch = buildMovedFile(myBasePath, beforeRevision, afterRevision);
         checkPathEndLine(movedPatch, c.getAfter());
         result.add(movedPatch);
       }
@@ -205,8 +205,9 @@
     }
   }
 
-  private static String[] tokenize(String text) {
-    return text.length() == 0 ?  new String[]{text} : new LineTokenizer(text).execute();
+  @NotNull
+  private static DiffString[] tokenize(@NotNull DiffString text) {
+    return text.length() == 0 ? new DiffString[]{text} : text.tokenize();
   }
 
   private FilePatch buildBinaryPatch(final String basePath,
@@ -221,20 +222,20 @@
     return patch;
   }
 
-  private static void addLineToHunk(final PatchHunk hunk, final String line, final PatchLine.Type type) {
+  private static void addLineToHunk(@NotNull final PatchHunk hunk, @NotNull final DiffString line, final PatchLine.Type type) {
     final PatchLine patchLine;
-    if (!line.endsWith("\n")) {
-      patchLine = new PatchLine(type, line);
+    if (!line.endsWith('\n')) {
+      patchLine = new PatchLine(type, line.toString());
       patchLine.setSuppressNewLine(true);
     }
     else {
-      patchLine = new PatchLine(type, line.substring(0, line.length()-1));
+      patchLine = new PatchLine(type, line.substring(0, line.length() - 1).toString());
     }
     hunk.addLine(patchLine);
   }
 
   private TextFilePatch buildMovedFile(final String basePath, final AirContentRevision beforeRevision,
-                                              final AirContentRevision afterRevision, final String[] lines) throws VcsException {
+                                       final AirContentRevision afterRevision) throws VcsException {
     final TextFilePatch result = buildPatchHeading(basePath, beforeRevision, afterRevision);
     final PatchHunk hunk = new PatchHunk(0, 0, 0, 0);
     result.addHunk(hunk);
@@ -242,14 +243,14 @@
   }
 
   private TextFilePatch buildAddedFile(final String basePath, final AirContentRevision afterRevision) throws VcsException {
-    final String content = afterRevision.getContentAsString();
+    final DiffString content = DiffString.createNullable(afterRevision.getContentAsString());
     if (content == null) {
       throw new VcsException("Failed to fetch content for added file " + afterRevision.getPath().getPath());
     }
-    String[] lines = tokenize(content);
+    DiffString[] lines = tokenize(content);
     TextFilePatch result = buildPatchHeading(basePath, afterRevision, afterRevision);
     PatchHunk hunk = new PatchHunk(-1, -1, 0, lines.length);
-    for(String line: lines) {
+    for (DiffString line : lines) {
       checkCanceled();
       addLineToHunk(hunk, line, PatchLine.Type.ADD);
     }
@@ -258,14 +259,14 @@
   }
 
   private TextFilePatch buildDeletedFile(String basePath, AirContentRevision beforeRevision) throws VcsException {
-    final String content = beforeRevision.getContentAsString();
+    final DiffString content = DiffString.createNullable(beforeRevision.getContentAsString());
     if (content == null) {
       throw new VcsException("Failed to fetch old content for deleted file " + beforeRevision.getPath().getPath());
     }
-    String[] lines = tokenize(content);
+    DiffString[] lines = tokenize(content);
     TextFilePatch result = buildPatchHeading(basePath, beforeRevision, beforeRevision);
     PatchHunk hunk = new PatchHunk(0, lines.length, -1, -1);
-    for(String line: lines) {
+    for (DiffString line : lines) {
       checkCanceled();
       addLineToHunk(hunk, line, PatchLine.Type.REMOVE);
     }
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/vfs/AbstractVcsVirtualFile.java b/platform/vcs-api/src/com/intellij/openapi/vcs/vfs/AbstractVcsVirtualFile.java
index 94b7e92..a28564d 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/vfs/AbstractVcsVirtualFile.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/vfs/AbstractVcsVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -44,20 +44,25 @@
       myParent = null;
   }
 
+  @Override
   @NotNull
   public VirtualFileSystem getFileSystem() {
     return myFileSystem;
   }
 
+  @Override
+  @NotNull
   public String getPath() {
     return myPath;
   }
 
+  @Override
   @NotNull
   public String getName() {
     return myName;
   }
 
+  @Override
   public String getPresentableName() {
     if (myRevision == null)
       return myName;
@@ -65,43 +70,53 @@
       return myName + " (" + myRevision + ")";
   }
 
+  @Override
   public boolean isWritable() {
     return false;
   }
 
+  @Override
   public boolean isValid() {
     return true;
   }
 
+  @Override
   public VirtualFile getParent() {
     return myParent;
 
   }
 
+  @Override
   public VirtualFile[] getChildren() {
     return null;
   }
 
+  @Override
   public InputStream getInputStream() throws IOException {
     return VfsUtilCore.byteStreamSkippingBOM(contentsToByteArray(), this);
   }
 
+  @Override
   @NotNull
   public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
     throw new RuntimeException(VcsFileSystem.COULD_NOT_IMPLEMENT_MESSAGE);
   }
 
+  @Override
   @NotNull
   public abstract byte[] contentsToByteArray() throws IOException;
 
+  @Override
   public long getModificationStamp() {
     return myModificationStamp;
   }
 
+  @Override
   public long getTimeStamp() {
     return myModificationStamp;
   }
 
+  @Override
   public long getLength() {
     try {
       return contentsToByteArray().length;
@@ -110,6 +125,7 @@
     }
   }
 
+  @Override
   public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) {
     if (postRunnable != null)
       postRunnable.run();
@@ -123,6 +139,7 @@
     myProcessingBeforeContentsChange = true;
     try {
       ApplicationManager.getApplication().runWriteAction(new Runnable() {
+        @Override
         public void run() {
           ((VcsFileSystem)getFileSystem()).fireBeforeContentsChange(this, AbstractVcsVirtualFile.this);
         }
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java
index 5b95283..2f3788a 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java
@@ -146,7 +146,7 @@
           comparisonPolicy = ComparisonPolicy.DEFAULT;
         }
         final TextCompareProcessor processor = new TextCompareProcessor(comparisonPolicy);
-        final ArrayList<LineFragment> lineFragments = processor.process(myOldDocument.getText(), myDocument.getText());
+        final List<LineFragment> lineFragments = processor.process(myOldDocument.getText(), myDocument.getText());
         myRanges = new ArrayList<BeforeAfter<TextRange>>(lineFragments.size());
         for (LineFragment lineFragment : lineFragments) {
           if (!lineFragment.isEqual()) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java
index 0f941a3..24884b4 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java
@@ -18,6 +18,7 @@
 import com.intellij.codeInsight.hint.EditorFragmentComponent;
 import com.intellij.codeInsight.hint.HintManagerImpl;
 import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ex.ActionUtil;
 import com.intellij.openapi.diff.DiffColors;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
@@ -165,9 +166,6 @@
     group.add(new ShowLineStatusRangeDiffAction(tracker, range, editor));
     group.add(new CopyLineStatusRangeAction(tracker, range));
 
-    @SuppressWarnings("unchecked")
-    final List<AnAction> actionList = (List<AnAction>)editorComponent.getClientProperty(AnAction.ourClientProperty);
-
     final JComponent toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.FILEHISTORY_VIEW_TOOLBAR, group, true).getComponent();
 
     final Color background = ((EditorEx)editor).getBackgroundColor();
@@ -218,6 +216,7 @@
       EditorFactory.getInstance().releaseEditor(uEditor);
     }
 
+    final List<AnAction> actionList = ActionUtil.getActions(editorComponent);
     final LightweightHint lightweightHint = new LightweightHint(component);
     HintListener closeListener = new HintListener() {
       public void hintHidden(final EventObject event) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java
index 7711dd3..e51a2a5 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java
@@ -38,6 +38,7 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.vfs.encoding.EncodingManager;
 import com.intellij.openapi.vfs.encoding.EncodingProjectManager;
+import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
 import com.intellij.util.WaitForProgressToShow;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -121,7 +122,7 @@
       diffData.setContents(createContent(project, content1, revision1, doc, charset, fileType, filePath.getPath()),
                            createContent(project, content2, revision2, doc, charset, fileType, filePath.getPath()));
     } else {
-      diffData.setContents(new FileContent(project, f1.get()), new FileContent(project, f2.get()));
+      diffData.setContents(createFileContent(project, f1.get(), revision1), createFileContent(project, f2.get(), revision2));
     }
     WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() {
       public void run() {
@@ -188,13 +189,22 @@
 
   private static DiffContent createContent(@NotNull Project project, byte[] content1, VcsFileRevision revision, Document doc, Charset charset, FileType fileType, String filePath) {
     if (isCurrent(revision) && (doc != null)) { return new DocumentContent(project, doc); }
+    if (isEmpty(revision)) { return SimpleContent.createEmpty(); }
     return new BinaryContent(project, content1, charset, fileType, filePath);
   }
 
+  private static DiffContent createFileContent(@NotNull Project project, VirtualFile file, VcsFileRevision revision) {
+    if (isEmpty(revision)) { return SimpleContent.createEmpty(); }
+    return new FileContent(project, file);
+  }
+
   private static boolean isCurrent(VcsFileRevision revision) {
     return revision instanceof CurrentRevision;
   }
 
+  private static boolean isEmpty(VcsFileRevision revision) {
+    return revision == null || VcsFileRevision.NULL.equals(revision);
+  }
 
   /**
    * Shows difference between two revisions of a file in a diff tool.
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java
index 26a2672..a3a5203 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.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.
@@ -79,12 +79,12 @@
 
   private static class MyHashKeyDescriptor implements KeyDescriptor<Hash> {
     @Override
-    public void save(DataOutput out, Hash value) throws IOException {
+    public void save(@NotNull DataOutput out, Hash value) throws IOException {
       out.writeUTF(value.asString());
     }
 
     @Override
-    public Hash read(DataInput in) throws IOException {
+    public Hash read(@NotNull DataInput in) throws IOException {
       return HashImpl.build(in.readUTF());
     }
 
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java
index 6a116d2..4f205e3 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java
@@ -23,6 +23,8 @@
 import com.intellij.openapi.actionSystem.DefaultActionGroup;
 import com.intellij.xdebugger.breakpoints.XBreakpointHandler;
 import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
+import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
+import com.intellij.xdebugger.frame.XStackFrame;
 import com.intellij.xdebugger.frame.XValueMarkerProvider;
 import com.intellij.xdebugger.stepping.XSmartStepIntoHandler;
 import com.intellij.xdebugger.ui.XDebugTabLayouter;
@@ -226,4 +228,9 @@
     return false;
   }
 
+  @Nullable
+  public XDebuggerEvaluator getEvaluator() {
+    XStackFrame frame = getSession().getCurrentStackFrame();
+    return frame == null ? null : frame.getEvaluator();
+  }
 }
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java
index 5345458..be71aac 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java
@@ -83,6 +83,7 @@
   /**
    * @deprecated use {@link #setCurrentStackFrame(com.intellij.xdebugger.frame.XExecutionStack, com.intellij.xdebugger.frame.XStackFrame)} instead
    */
+  @SuppressWarnings("UnusedDeclaration")
   void setCurrentStackFrame(@NotNull XStackFrame frame);
 
   /**
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java
index a6b07b3..676fb3f 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java
@@ -100,4 +100,11 @@
   public Icon getTemporaryIcon() {
     return AllIcons.Debugger.Db_temporary_breakpoint;
   }
+
+  /**
+   * Higher priority wins if several types available for the line(s)
+   */
+  public int getPriority() {
+    return 0;
+  }
 }
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java
index 1cf23c5..7130b77 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java
@@ -115,7 +115,7 @@
    * @param offset             offset
    * @param sideEffectsAllowed if this parameter is false, the expression should not have any side effects when evaluated
    *                           (such expressions are evaluated in quick popups)
-   * @return pair of text range of expression (to display as link) and actual expression to evaluate (optional, could be null)
+   * @return pair of text range of expression (to highlight as link) and actual expression to evaluate (optional, could be null)
    */
   @Nullable
   public Pair<TextRange, String> getExpressionAtOffset(@NotNull Project project, @NotNull Document document, int offset, boolean sideEffectsAllowed) {
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XStackFrame.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XStackFrame.java
index eaa6420..ba5d5f3 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XStackFrame.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XStackFrame.java
@@ -22,6 +22,7 @@
 import com.intellij.xdebugger.XDebuggerBundle;
 import com.intellij.xdebugger.XSourcePosition;
 import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -63,7 +64,7 @@
    * Customize presentation of the stack frame in frames list
    * @param component component
    */
-  public void customizePresentation(ColoredTextContainer component) {
+  public void customizePresentation(@NotNull ColoredTextContainer component) {
     XSourcePosition position = getSourcePosition();
     if (position != null) {
       component.append(position.getFile().getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/stepping/PsiBackedSmartStepIntoVariant.java b/platform/xdebugger-api/src/com/intellij/xdebugger/stepping/PsiBackedSmartStepIntoVariant.java
index f272816..d17f8e0 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/stepping/PsiBackedSmartStepIntoVariant.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/stepping/PsiBackedSmartStepIntoVariant.java
@@ -36,6 +36,7 @@
     assert myPresentation != null: "Invalid presentation:" + myElement;
   }
 
+  @Override
   public String getText() {
     String location = myPresentation.getLocationString();
     return myPresentation.getPresentableText() + (location != null ? " " + location: "");
@@ -46,6 +47,7 @@
     return myPresentation.getIcon(false);
   }
 
+  @NotNull
   public T getElement() {
     return myElement;
   }
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/stepping/XSmartStepIntoHandler.java b/platform/xdebugger-api/src/com/intellij/xdebugger/stepping/XSmartStepIntoHandler.java
index 46dcaa2..56b098d 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/stepping/XSmartStepIntoHandler.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/stepping/XSmartStepIntoHandler.java
@@ -40,7 +40,7 @@
    * when <code>variant</code> function/method is reached
    * @param variant selected variant
    */
-  public abstract void startStepInto(Variant variant);
+  public abstract void startStepInto(@NotNull Variant variant);
 
   /**
    * @return title for popup which will be shown to select method/function
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java
index 42bee65..82c0522 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java
@@ -15,11 +15,15 @@
  */
 package com.intellij.xdebugger.impl;
 
+import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.extensions.ExtensionPointName;
 import com.intellij.openapi.extensions.Extensions;
 import com.intellij.openapi.project.Project;
 import com.intellij.xdebugger.AbstractDebuggerSession;
-import com.intellij.xdebugger.impl.actions.*;
+import com.intellij.xdebugger.impl.actions.DebuggerActionHandler;
+import com.intellij.xdebugger.impl.actions.DebuggerToggleActionHandler;
+import com.intellij.xdebugger.impl.actions.EditBreakpointActionHandler;
+import com.intellij.xdebugger.impl.actions.MarkObjectActionHandler;
 import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider;
 import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler;
 import com.intellij.xdebugger.impl.settings.DebuggerSettingsPanelProvider;
@@ -32,6 +36,19 @@
 public abstract class DebuggerSupport {
   private static final ExtensionPointName<DebuggerSupport> EXTENSION_POINT = ExtensionPointName.create("com.intellij.xdebugger.debuggerSupport");
 
+  protected static final class DisabledActionHandler extends DebuggerActionHandler {
+    public static final DisabledActionHandler INSTANCE = new DisabledActionHandler();
+
+    @Override
+    public void perform(@NotNull Project project, AnActionEvent event) {
+    }
+
+    @Override
+    public boolean isEnabled(@NotNull Project project, AnActionEvent event) {
+      return false;
+    }
+  }
+
   @NotNull
   public static DebuggerSupport[] getDebuggerSupports() {
     return Extensions.getExtensions(EXTENSION_POINT);
@@ -95,6 +112,10 @@
   @NotNull
   public abstract DebuggerActionHandler getAddToWatchesActionHandler();
 
+  public DebuggerActionHandler getEvaluateInConsoleActionHandler() {
+    return DisabledActionHandler.INSTANCE;
+  }
+
   @NotNull
   public abstract DebuggerToggleActionHandler getMuteBreakpointsHandler();
 
@@ -116,6 +137,6 @@
         return support;
       }
     }
-    return null;
+    throw new IllegalStateException();
   }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
index ea407a2..337f6fe 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
@@ -51,6 +51,7 @@
 import com.intellij.ui.AppUIUtil;
 import com.intellij.util.EventDispatcher;
 import com.intellij.util.SmartList;
+import com.intellij.util.containers.SmartHashSet;
 import com.intellij.util.ui.UIUtil;
 import com.intellij.xdebugger.*;
 import com.intellij.xdebugger.breakpoints.*;
@@ -67,6 +68,7 @@
 import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
 import com.intellij.xdebugger.stepping.XSmartStepIntoHandler;
 import com.intellij.xdebugger.stepping.XSmartStepIntoVariant;
+import gnu.trove.THashMap;
 import gnu.trove.THashSet;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -86,8 +88,8 @@
                                                                                                false);
   private XDebugProcess myDebugProcess;
   private final Map<XBreakpoint<?>, CustomizedBreakpointPresentation> myRegisteredBreakpoints =
-    new HashMap<XBreakpoint<?>, CustomizedBreakpointPresentation>();
-  private final Set<XBreakpoint<?>> myInactiveSlaveBreakpoints = new HashSet<XBreakpoint<?>>();
+    new THashMap<XBreakpoint<?>, CustomizedBreakpointPresentation>();
+  private final Set<XBreakpoint<?>> myInactiveSlaveBreakpoints = new SmartHashSet<XBreakpoint<?>>();
   private boolean myBreakpointsMuted;
   private boolean myBreakpointsDisabled;
   private final XDebuggerManagerImpl myDebuggerManager;
@@ -329,6 +331,7 @@
     return myValueMarkers;
   }
 
+  @SuppressWarnings("unchecked") //need to compile under 1.8, please do not remove before checking
   private static XBreakpointType getBreakpointTypeClass(final XBreakpointHandler handler) {
     return XDebuggerUtil.getInstance().findBreakpointType(handler.getBreakpointTypeClass());
   }
@@ -351,12 +354,9 @@
       handler.registerBreakpoint(b);
     }
     if (!register) {
-      boolean removed = false;
+      boolean removed;
       synchronized (myRegisteredBreakpoints) {
-        if (myRegisteredBreakpoints.containsKey(b)) {
-          myRegisteredBreakpoints.remove(b);
-          removed = true;
-        }
+        removed = myRegisteredBreakpoints.remove(b) != null;
       }
       if (removed) {
         handler.unregisterBreakpoint(b, temporary);
@@ -780,7 +780,7 @@
       myBreakpointsDisabled = false;
       new ReadAction() {
         @Override
-        protected void run(final Result result) {
+        protected void run(@NotNull Result result) {
           processAllBreakpoints(true, false);
         }
       }.execute();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java
index c56f2c7..fbfe184 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java
@@ -50,11 +50,14 @@
   private final XDebuggerEvaluateActionHandler myEvaluateHandler;
   private final XQuickEvaluateHandler myQuickEvaluateHandler;
   private final XDebuggerSettingsPanelProviderImpl mySettingsPanelProvider;
+
   private final XAddToWatchesFromEditorActionHandler myAddToWatchesActionHandler;
+  private final DebuggerActionHandler myEvaluateInConsoleActionHandler = new XEvaluateInConsoleFromEditorActionHandler();
+
   private final DebuggerToggleActionHandler myMuteBreakpointsHandler;
   private final DebuggerActionHandler mySmartStepIntoHandler;
   private final XMarkObjectActionHandler myMarkObjectActionHandler;
-  private final EditBreakpointActionHandler myEditBreakpointActoinHandler;
+  private final EditBreakpointActionHandler myEditBreakpointActionHandler;
 
   public XDebuggerSupport() {
     myBreakpointPanelProvider = new XBreakpointPanelProvider();
@@ -62,26 +65,31 @@
     myToggleTemporaryLineBreakpointActionHandler = new XToggleLineBreakpointActionHandler(true);
     myAddToWatchesActionHandler = new XAddToWatchesFromEditorActionHandler();
     myStepOverHandler = new XDebuggerSuspendedActionHandler() {
+      @Override
       protected void perform(@NotNull final XDebugSession session, final DataContext dataContext) {
         session.stepOver(false);
       }
     };
     myStepIntoHandler = new XDebuggerSuspendedActionHandler() {
+      @Override
       protected void perform(@NotNull final XDebugSession session, final DataContext dataContext) {
         session.stepInto();
       }
     };
     myStepOutHandler = new XDebuggerSuspendedActionHandler() {
+      @Override
       protected void perform(@NotNull final XDebugSession session, final DataContext dataContext) {
         session.stepOut();
       }
     };
     myForceStepOverHandler = new XDebuggerSuspendedActionHandler() {
+      @Override
       protected void perform(@NotNull final XDebugSession session, final DataContext dataContext) {
         session.stepOver(true);
       }
     };
     myForceStepIntoHandler = new XDebuggerSuspendedActionHandler() {
+      @Override
       protected void perform(@NotNull final XDebugSession session, final DataContext dataContext) {
         session.forceStepInto();
       }
@@ -90,16 +98,19 @@
     myRunToCursorHandler = new XDebuggerRunToCursorActionHandler(false);
     myForceRunToCursor = new XDebuggerRunToCursorActionHandler(true);
     myResumeHandler = new XDebuggerActionHandler() {
+      @Override
       protected boolean isEnabled(@NotNull final XDebugSession session, final DataContext dataContext) {
         return session.isPaused();
       }
 
+      @Override
       protected void perform(@NotNull final XDebugSession session, final DataContext dataContext) {
         session.resume();
       }
     };
     myPauseHandler = new XDebuggerPauseActionHandler();
     myShowExecutionPointHandler = new XDebuggerSuspendedActionHandler() {
+      @Override
       protected void perform(@NotNull final XDebugSession session, final DataContext dataContext) {
         session.showExecutionPoint();
       }
@@ -109,64 +120,76 @@
     myQuickEvaluateHandler = new XQuickEvaluateHandler();
     mySettingsPanelProvider = new XDebuggerSettingsPanelProviderImpl();
     myMarkObjectActionHandler = new XMarkObjectActionHandler();
-    myEditBreakpointActoinHandler = new XDebuggerEditBreakpointActionHandler();
+    myEditBreakpointActionHandler = new XDebuggerEditBreakpointActionHandler();
   }
 
+  @Override
   @NotNull
   public BreakpointPanelProvider<?> getBreakpointPanelProvider() {
     return myBreakpointPanelProvider;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getStepOverHandler() {
     return myStepOverHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getStepIntoHandler() {
     return myStepIntoHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getSmartStepIntoHandler() {
     return mySmartStepIntoHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getStepOutHandler() {
     return myStepOutHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getForceStepOverHandler() {
     return myForceStepOverHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getForceStepIntoHandler() {
     return myForceStepIntoHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getRunToCursorHandler() {
     return myRunToCursorHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getForceRunToCursorHandler() {
     return myForceRunToCursor;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getResumeActionHandler() {
     return myResumeHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getPauseHandler() {
     return myPauseHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getToggleLineBreakpointHandler() {
     return myToggleLineBreakpointActionHandler;
@@ -178,16 +201,19 @@
     return myToggleTemporaryLineBreakpointActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getShowExecutionPointHandler() {
     return myShowExecutionPointHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerActionHandler getEvaluateHandler() {
     return myEvaluateHandler;
   }
 
+  @Override
   @NotNull
   public QuickEvaluateHandler getQuickEvaluateHandler() {
     return myQuickEvaluateHandler;
@@ -200,6 +226,13 @@
   }
 
   @NotNull
+  @Override
+  public DebuggerActionHandler getEvaluateInConsoleActionHandler() {
+    return myEvaluateInConsoleActionHandler;
+  }
+
+  @Override
+  @NotNull
   public DebuggerToggleActionHandler getMuteBreakpointsHandler() {
     return myMuteBreakpointsHandler;
   }
@@ -218,12 +251,12 @@
   @NotNull
   @Override
   public EditBreakpointActionHandler getEditBreakpointAction() {
-    return myEditBreakpointActoinHandler;
+    return myEditBreakpointActionHandler;
   }
 
+  @Override
   @NotNull
   public DebuggerSettingsPanelProvider getSettingsPanelProvider() {
     return mySettingsPanelProvider;
   }
-
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java
index 76a360f..191b8f2 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java
@@ -75,12 +75,15 @@
 
   @Override
   public void toggleLineBreakpoint(@NotNull final Project project, @NotNull final VirtualFile file, final int line, boolean temporary) {
+    XLineBreakpointType<?> typeWinner = null;
     for (XLineBreakpointType<?> type : getLineBreakpointTypes()) {
-      if (type.canPutAt(file, line, project)) {
-        toggleLineBreakpoint(project, type, file, line, temporary);
-        return;
+      if (type.canPutAt(file, line, project) && (typeWinner == null || type.getPriority() > typeWinner.getPriority())) {
+        typeWinner = type;
       }
     }
+    if (typeWinner != null) {
+      toggleLineBreakpoint(project, typeWinner, file, line, temporary);
+    }
   }
 
   @Override
@@ -222,34 +225,34 @@
   @Override
   public void iterateLine(@NotNull Project project, @NotNull Document document, int line, @NotNull Processor<PsiElement> processor) {
     PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
-    if (file == null) return;
+    if (file == null) {
+      return;
+    }
 
     int lineStart;
     int lineEnd;
-
     try {
       lineStart = document.getLineStartOffset(line);
       lineEnd = document.getLineEndOffset(line);
     }
-    catch (IndexOutOfBoundsException e) {
+    catch (IndexOutOfBoundsException ignored) {
       return;
     }
 
     PsiElement element;
-
-    int off = lineStart;
-    while (off < lineEnd) {
-      element = file.findElementAt(off);
+    int offset = lineStart;
+    while (offset < lineEnd) {
+      element = file.findElementAt(offset);
       if (element != null) {
         if (!processor.process(element)) {
           return;
         }
         else {
-          off = element.getTextRange().getEndOffset();
+          offset = element.getTextRange().getEndOffset();
         }
       }
       else {
-        off++;
+        offset++;
       }
     }
   }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AddToWatchesAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AddToWatchesAction.java
index 33bfc5a..c93496b 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AddToWatchesAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/AddToWatchesAction.java
@@ -18,10 +18,7 @@
 import com.intellij.xdebugger.impl.DebuggerSupport;
 import org.jetbrains.annotations.NotNull;
 
-/**
- * @author nik
- */
-public class AddToWatchesAction extends XDebuggerActionBase {
+final class AddToWatchesAction extends XDebuggerActionBase {
   public AddToWatchesAction() {
     super(true);
   }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateAction.java
index 39e5949..ea17644 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateAction.java
@@ -15,17 +15,18 @@
  */
 package com.intellij.xdebugger.impl.actions;
 
-import org.jetbrains.annotations.NotNull;
 import com.intellij.xdebugger.impl.DebuggerSupport;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * @author nik
  */
-public class EvaluateAction extends XDebuggerActionBase {
+final class EvaluateAction extends XDebuggerActionBase {
   public EvaluateAction() {
     super(true);
   }
 
+  @Override
   @NotNull
   protected DebuggerActionHandler getHandler(@NotNull final DebuggerSupport debuggerSupport) {
     return debuggerSupport.getEvaluateHandler();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateInConsoleAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateInConsoleAction.java
new file mode 100644
index 0000000..ebfbb94
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EvaluateInConsoleAction.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xdebugger.impl.actions;
+
+import com.intellij.xdebugger.impl.DebuggerSupport;
+import org.jetbrains.annotations.NotNull;
+
+final class EvaluateInConsoleAction extends XDebuggerActionBase {
+  public EvaluateInConsoleAction() {
+    super(true);
+  }
+
+  @NotNull
+  @Override
+  protected DebuggerActionHandler getHandler(@NotNull DebuggerSupport debuggerSupport) {
+    return debuggerSupport.getEvaluateInConsoleActionHandler();
+  }
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/QuickEvaluateAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/QuickEvaluateAction.java
index 25e1b01..be54d59 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/QuickEvaluateAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/QuickEvaluateAction.java
@@ -40,6 +40,7 @@
     super(true);
   }
 
+  @Override
   @NotNull
   protected DebuggerActionHandler getHandler(@NotNull final DebuggerSupport debuggerSupport) {
     return new QuickEvaluateHandlerWrapper(debuggerSupport.getQuickEvaluateHandler());
@@ -52,6 +53,7 @@
       myHandler = handler;
     }
 
+    @Override
     public void perform(@NotNull final Project project, final AnActionEvent event) {
       Editor editor = event.getData(CommonDataKeys.EDITOR);
       if (editor != null) {
@@ -61,11 +63,16 @@
       }
     }
 
+    @Override
     public boolean isEnabled(@NotNull final Project project, final AnActionEvent event) {
-      if (!myHandler.isEnabled(project)) return false;
+      if (!myHandler.isEnabled(project)) {
+        return false;
+      }
 
       Editor editor = event.getData(CommonDataKeys.EDITOR);
-      if (editor == null) return false;
+      if (editor == null) {
+        return false;
+      }
 
       InputEvent inputEvent = event.getInputEvent();
       if (inputEvent instanceof MouseEvent && inputEvent.isAltDown()) {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ResumeAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ResumeAction.java
index c669ec2..011c41b 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ResumeAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ResumeAction.java
@@ -19,7 +19,7 @@
 import com.intellij.openapi.actionSystem.ActionPlaces;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.project.DumbAware;
 import com.intellij.openapi.project.Project;
 import com.intellij.xdebugger.AbstractDebuggerSession;
 import com.intellij.xdebugger.impl.DebuggerSupport;
@@ -28,7 +28,7 @@
 /**
  * @author nik
  */
-public class ResumeAction extends XDebuggerActionBase {
+public class ResumeAction extends XDebuggerActionBase implements DumbAware {
   @Override
   protected boolean isEnabled(AnActionEvent e) {
     Project project = e.getData(CommonDataKeys.PROJECT);
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ShowExecutionPointAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ShowExecutionPointAction.java
index a00e261..12def64 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ShowExecutionPointAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ShowExecutionPointAction.java
@@ -15,13 +15,14 @@
  */
 package com.intellij.xdebugger.impl.actions;
 
-import org.jetbrains.annotations.NotNull;
 import com.intellij.xdebugger.impl.DebuggerSupport;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * @author nik
  */
 public class ShowExecutionPointAction extends XDebuggerActionBase {
+  @Override
   @NotNull
   protected DebuggerActionHandler getHandler(@NotNull final DebuggerSupport debuggerSupport) {
     return debuggerSupport.getShowExecutionPointHandler();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/SmartStepIntoAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/SmartStepIntoAction.java
index f886f1f..adc2589 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/SmartStepIntoAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/SmartStepIntoAction.java
@@ -15,13 +15,14 @@
  */
 package com.intellij.xdebugger.impl.actions;
 
-import org.jetbrains.annotations.NotNull;
 import com.intellij.xdebugger.impl.DebuggerSupport;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * @author nik
  */
-public class SmartStepIntoAction extends XDebuggerActionBase {
+final class SmartStepIntoAction extends XDebuggerActionBase {
+  @Override
   @NotNull
   protected DebuggerActionHandler getHandler(@NotNull final DebuggerSupport debuggerSupport) {
     return debuggerSupport.getSmartStepIntoHandler();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActionBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActionBase.java
index 8ed0430..5e3a6c1 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActionBase.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActionBase.java
@@ -39,8 +39,7 @@
     Presentation presentation = event.getPresentation();
     boolean hidden = isHidden(event);
     if (hidden) {
-      presentation.setEnabled(false);
-      presentation.setVisible(false);
+      presentation.setEnabledAndVisible(false);
       return;
     }
 
@@ -100,7 +99,7 @@
   }
 
   protected boolean isHidden(AnActionEvent event) {
-    final Project project = event.getData(CommonDataKeys.PROJECT);
+    final Project project = event.getProject();
     if (project != null) {
       for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
         if (!getHandler(support).isHidden(project, event)) {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerSuspendedActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerSuspendedActionHandler.java
index 70ecabd..0137fac 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerSuspendedActionHandler.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerSuspendedActionHandler.java
@@ -15,16 +15,16 @@
  */
 package com.intellij.xdebugger.impl.actions;
 
+import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.xdebugger.XDebugSession;
 import com.intellij.xdebugger.impl.actions.handlers.XDebuggerActionHandler;
-import com.intellij.openapi.actionSystem.DataContext;
 import org.jetbrains.annotations.NotNull;
 
 /**
  * @author nik
  */
 public abstract class XDebuggerSuspendedActionHandler extends XDebuggerActionHandler {
-
+  @Override
   protected boolean isEnabled(final @NotNull XDebugSession session, final DataContext dataContext) {
     return session.isSuspended();
   }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XAddToWatchesFromEditorActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XAddToWatchesFromEditorActionHandler.java
index 3b52fa5..b1aac45 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XAddToWatchesFromEditorActionHandler.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XAddToWatchesFromEditorActionHandler.java
@@ -20,7 +20,7 @@
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.xdebugger.XDebugSession;
-import com.intellij.xdebugger.frame.XStackFrame;
+import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
 import com.intellij.xdebugger.impl.XDebugSessionImpl;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -35,17 +35,17 @@
   }
 
   @Nullable
-  private static String getTextToEvaluate(DataContext dataContext, XDebugSession session) {
+  protected static String getTextToEvaluate(DataContext dataContext, XDebugSession session) {
     final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
     if (editor == null) {
       return null;
     }
 
     String text = editor.getSelectionModel().getSelectedText();
-    if (text == null && session.isSuspended()) {
-      final XStackFrame stackFrame = session.getCurrentStackFrame();
-      if (stackFrame != null) {
-        text = XDebuggerEvaluateActionHandler.getExpressionText(stackFrame.getEvaluator(), editor.getProject(), editor);
+    if (text == null) {
+      XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator();
+      if (evaluator != null) {
+        text = XDebuggerEvaluateActionHandler.getExpressionText(evaluator, editor.getProject(), editor);
       }
     }
 
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerActionHandler.java
index 3ac02a6..fa079b3 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerActionHandler.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerActionHandler.java
@@ -15,19 +15,19 @@
  */
 package com.intellij.xdebugger.impl.actions.handlers;
 
-import com.intellij.xdebugger.impl.actions.DebuggerActionHandler;
-import com.intellij.xdebugger.XDebuggerManager;
-import com.intellij.xdebugger.XDebugSession;
-import com.intellij.openapi.project.Project;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XDebugSession;
+import com.intellij.xdebugger.XDebuggerManager;
+import com.intellij.xdebugger.impl.actions.DebuggerActionHandler;
 import org.jetbrains.annotations.NotNull;
 
 /**
  * @author nik
  */
 public abstract class XDebuggerActionHandler extends DebuggerActionHandler {
-
+  @Override
   public void perform(@NotNull final Project project, final AnActionEvent event) {
     XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
     if (session != null) {
@@ -35,6 +35,7 @@
     }
   }
 
+  @Override
   public boolean isEnabled(@NotNull final Project project, final AnActionEvent event) {
     XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
     return session != null && isEnabled(session, event.getDataContext());
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java
index d892aca..1a24b30 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java
@@ -28,7 +28,6 @@
 import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
 import com.intellij.xdebugger.frame.XStackFrame;
 import com.intellij.xdebugger.frame.XValue;
-import com.intellij.xdebugger.impl.actions.XDebuggerSuspendedActionHandler;
 import com.intellij.xdebugger.impl.evaluate.XDebuggerEvaluationDialog;
 import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
 import org.jetbrains.annotations.NotNull;
@@ -37,14 +36,15 @@
 /**
  * @author nik
  */
-public class XDebuggerEvaluateActionHandler extends XDebuggerSuspendedActionHandler {
+public class XDebuggerEvaluateActionHandler extends XDebuggerActionHandler {
   @Override
   protected void perform(@NotNull final XDebugSession session, final DataContext dataContext) {
     XDebuggerEditorsProvider editorsProvider = session.getDebugProcess().getEditorsProvider();
     XStackFrame stackFrame = session.getCurrentStackFrame();
-    if (stackFrame == null) return;
-    final XDebuggerEvaluator evaluator = stackFrame.getEvaluator();
-    if (evaluator == null) return;
+    final XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator();
+    if (evaluator == null) {
+      return;
+    }
 
     @Nullable Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
 
@@ -64,7 +64,7 @@
         text = value.getEvaluationExpression();
       }
     }
-    new XDebuggerEvaluationDialog(session, editorsProvider, evaluator, StringUtil.notNullize(text), stackFrame.getSourcePosition()).show();
+    new XDebuggerEvaluationDialog(session, editorsProvider, evaluator, StringUtil.notNullize(text), stackFrame == null ? null : stackFrame.getSourcePosition()).show();
   }
 
   @Nullable
@@ -86,11 +86,6 @@
 
   @Override
   protected boolean isEnabled(final @NotNull XDebugSession session, final DataContext dataContext) {
-    if (!super.isEnabled(session, dataContext)) {
-      return false;
-    }
-
-    XStackFrame stackFrame = session.getCurrentStackFrame();
-    return stackFrame != null && stackFrame.getEvaluator() != null;
+    return session.getDebugProcess().getEvaluator() != null;
   }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerSmartStepIntoHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerSmartStepIntoHandler.java
index 4a933b7..6d09b8f 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerSmartStepIntoHandler.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerSmartStepIntoHandler.java
@@ -15,21 +15,21 @@
  */
 package com.intellij.xdebugger.impl.actions.handlers;
 
-import org.jetbrains.annotations.NotNull;
-import com.intellij.xdebugger.XDebugSession;
-import com.intellij.xdebugger.XSourcePosition;
-import com.intellij.xdebugger.stepping.XSmartStepIntoHandler;
-import com.intellij.xdebugger.stepping.XSmartStepIntoVariant;
-import com.intellij.xdebugger.impl.actions.XDebuggerSuspendedActionHandler;
-import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
 import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.fileEditor.TextEditor;
 import com.intellij.openapi.ui.popup.JBPopupFactory;
 import com.intellij.openapi.ui.popup.PopupStep;
 import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
 import com.intellij.ui.awt.RelativePoint;
+import com.intellij.xdebugger.XDebugSession;
+import com.intellij.xdebugger.XSourcePosition;
+import com.intellij.xdebugger.impl.actions.XDebuggerSuspendedActionHandler;
+import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
+import com.intellij.xdebugger.stepping.XSmartStepIntoHandler;
+import com.intellij.xdebugger.stepping.XSmartStepIntoVariant;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import java.util.List;
@@ -39,10 +39,12 @@
  */
 public class XDebuggerSmartStepIntoHandler extends XDebuggerSuspendedActionHandler {
 
+  @Override
   protected boolean isEnabled(@NotNull XDebugSession session, DataContext dataContext) {
     return super.isEnabled(session, dataContext) && session.getDebugProcess().getSmartStepIntoHandler() != null;
   }
 
+  @Override
   protected void perform(@NotNull XDebugSession session, DataContext dataContext) {
     final XSmartStepIntoHandler<?> handler = session.getDebugProcess().getSmartStepIntoHandler();
     final XSourcePosition position = session.getCurrentPosition();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XEvaluateInConsoleFromEditorActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XEvaluateInConsoleFromEditorActionHandler.java
new file mode 100644
index 0000000..fb5f3d7
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XEvaluateInConsoleFromEditorActionHandler.java
@@ -0,0 +1,86 @@
+package com.intellij.xdebugger.impl.actions.handlers;
+
+import com.intellij.execution.console.ConsoleExecuteAction;
+import com.intellij.execution.console.LanguageConsoleView;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.ex.ActionUtil;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xdebugger.XDebugSession;
+import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class XEvaluateInConsoleFromEditorActionHandler extends XAddToWatchesFromEditorActionHandler {
+  @Override
+  protected boolean isEnabled(@NotNull XDebugSession session, DataContext dataContext) {
+    return super.isEnabled(session, dataContext) && getConsoleExecuteAction(session) != null;
+  }
+
+  @Nullable
+  private static ConsoleExecuteAction getConsoleExecuteAction(@NotNull XDebugSession session) {
+    return getConsoleExecuteAction(session.getConsoleView());
+  }
+
+  @Nullable
+  public static ConsoleExecuteAction getConsoleExecuteAction(@Nullable ConsoleView consoleView) {
+    if (!(consoleView instanceof LanguageConsoleView)) {
+      return null;
+    }
+
+    List<AnAction> actions = ActionUtil.getActions(((LanguageConsoleView)consoleView).getConsole().getConsoleEditor().getComponent());
+    ConsoleExecuteAction action = ContainerUtil.findInstance(actions, ConsoleExecuteAction.class);
+    return action == null || !action.isEnabled() ? null : action;
+  }
+
+  @Override
+  protected void perform(@NotNull XDebugSession session, DataContext dataContext) {
+    Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
+    if (editor == null || !(editor instanceof EditorEx)) {
+      return;
+    }
+
+    int selectionStart = editor.getSelectionModel().getSelectionStart();
+    int selectionEnd = editor.getSelectionModel().getSelectionEnd();
+    String text;
+    TextRange range;
+    if (selectionStart != selectionEnd) {
+      range = new TextRange(selectionStart, selectionEnd);
+      text = editor.getDocument().getText(range);
+    }
+    else {
+      XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator();
+      if (evaluator != null) {
+        Pair<TextRange, String> expressionInfo = evaluator.getExpressionAtOffset(session.getProject(), editor.getDocument(), selectionStart, true);
+        if (expressionInfo == null) {
+          return;
+        }
+
+        // todo check - is it wrong in case of not-null expressionInfo.second - copied (to console history document) text (text range) could be not correct statement?
+        range = expressionInfo.first;
+        text = XDebuggerEvaluateActionHandler.getExpressionText(expressionInfo, editor.getDocument());
+      }
+      else {
+        return;
+      }
+    }
+
+    if (StringUtil.isEmptyOrSpaces(text)) {
+      return;
+    }
+
+    ConsoleExecuteAction action = getConsoleExecuteAction(session);
+    if (action != null) {
+      action.execute(range, text, (EditorEx)editor);
+    }
+  }
+}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XToggleLineBreakpointActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XToggleLineBreakpointActionHandler.java
index 03ae018..e100741 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XToggleLineBreakpointActionHandler.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XToggleLineBreakpointActionHandler.java
@@ -15,10 +15,12 @@
  */
 package com.intellij.xdebugger.impl.actions.handlers;
 
+import com.intellij.codeInsight.folding.impl.FoldingUtil;
 import com.intellij.codeInsight.folding.impl.actions.ExpandRegionAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.FoldRegion;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.xdebugger.XDebuggerUtil;
@@ -63,20 +65,42 @@
     XSourcePosition position = XDebuggerUtilImpl.getCaretPosition(project, event.getDataContext());
     if (position == null) return;
 
-    ExpandRegionAction.expandRegionAtCaret(project, event.getData(CommonDataKeys.EDITOR));
+    Editor editor = event.getData(CommonDataKeys.EDITOR);
 
-    int line = position.getLine();
+    // for folded text check each line and find out type with the biggest priority
+    int lineStart = position.getLine();
+    int linesEnd = lineStart;
+    FoldRegion region = FoldingUtil.findFoldRegionStartingAtLine(editor, lineStart);
+    if (region != null && !region.isExpanded()) {
+      linesEnd = region.getDocument().getLineNumber(region.getEndOffset());
+    }
+
     VirtualFile file = position.getFile();
     final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager();
-    for (XLineBreakpointType<?> type : XDebuggerUtil.getInstance().getLineBreakpointTypes()) {
-      final XLineBreakpoint<? extends XBreakpointProperties> breakpoint = breakpointManager.findBreakpointAtLine(type, file, line);
-      if (breakpoint != null && myTemporary && !breakpoint.isTemporary()) {
-        breakpoint.setTemporary(true);
-      } else if (type.canPutAt(file, line, project) || breakpoint != null) {
-        XDebuggerUtil.getInstance().toggleLineBreakpoint(project, type, file, line, myTemporary);
-        return;
+    XLineBreakpointType<?>[] lineTypes = XDebuggerUtil.getInstance().getLineBreakpointTypes();
+    XLineBreakpointType<?> typeWinner = null;
+    int lineWinner = -1;
+    for (int line = lineStart; line <= linesEnd; line++) {
+      for (XLineBreakpointType<?> type : lineTypes) {
+        final XLineBreakpoint<? extends XBreakpointProperties> breakpoint = breakpointManager.findBreakpointAtLine(type, file, line);
+        if (breakpoint != null && myTemporary && !breakpoint.isTemporary()) {
+          breakpoint.setTemporary(true);
+        } else if (type.canPutAt(file, line, project) || breakpoint != null) {
+          if (typeWinner == null || type.getPriority() > typeWinner.getPriority()) {
+            typeWinner = type;
+            lineWinner = line;
+          }
+        }
       }
     }
-  }
 
+    if (typeWinner != null) {
+      XDebuggerUtil.getInstance().toggleLineBreakpoint(project, typeWinner, file, lineWinner, myTemporary);
+    }
+
+    ExpandRegionAction.expandRegionAtCaret(project, editor);
+    if (editor != null && lineStart != lineWinner) {
+      editor.getCaretModel().moveToOffset(editor.getDocument().getLineStartOffset(lineWinner));
+    }
+  }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java
index 530fb99..5f95c73 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java
@@ -15,10 +15,7 @@
  */
 package com.intellij.xdebugger.impl.breakpoints;
 
-import com.intellij.util.xmlb.annotations.Attribute;
-import com.intellij.util.xmlb.annotations.Property;
-import com.intellij.util.xmlb.annotations.Tag;
-import com.intellij.util.xmlb.annotations.Transient;
+import com.intellij.util.xmlb.annotations.*;
 import com.intellij.xdebugger.breakpoints.SuspendPolicy;
 import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
@@ -36,8 +33,8 @@
   private Element myPropertiesElement;
   private SuspendPolicy mySuspendPolicy = SuspendPolicy.ALL;
   private boolean myLogMessage;
-  private String myLogExpression;
-  private String myCondition;
+  private LogExpression myLogExpression;
+  private Condition myCondition;
   private XBreakpointDependencyState myDependencyState;
   private long myTimeStamp;
 
@@ -104,22 +101,52 @@
     myLogMessage = logMessage;
   }
 
-  @Tag("log-expression")
+  @Transient
   public String getLogExpression() {
+    return myLogExpression != null ? myLogExpression.myExpression : null;
+  }
+
+  public void setLogExpression(String expression) {
+    if (expression != null) {
+      myLogExpression = new LogExpression();
+      myLogExpression.myExpression = expression;
+    }
+    else {
+      myLogExpression = null;
+    }
+  }
+
+  @Property(surroundWithTag = false)
+  public LogExpression getLogExpressionObject() {
     return myLogExpression;
   }
 
-  public void setLogExpression(final String logExpression) {
-    myLogExpression = logExpression;
+  public void setLogExpressionObject(final LogExpression logExpression) {
+    setLogExpression(logExpression.myOldExpression != null ? logExpression.myOldExpression : logExpression.myExpression);
   }
 
-  @Tag("condition")
+  @Transient
   public String getCondition() {
+    return myCondition != null ? myCondition.myExpression : null;
+  }
+
+  public void setCondition(String condition) {
+    if (condition != null) {
+      myCondition = new Condition();
+      myCondition.myExpression = condition;
+    }
+    else {
+      myCondition = null;
+    }
+  }
+
+  @Property(surroundWithTag = false)
+  public Condition getConditionObject() {
     return myCondition;
   }
 
-  public void setCondition(final String condition) {
-    myCondition = condition;
+  public void setConditionObject(final Condition condition) {
+    setCondition(condition.myOldExpression != null ? condition.myOldExpression : condition.myExpression);
   }
 
   @Property(surroundWithTag = false)
@@ -142,4 +169,24 @@
   public void setTimeStamp(long timeStamp) {
     myTimeStamp = timeStamp;
   }
+
+  void applyDefaults(BreakpointState state) {
+    state.mySuspendPolicy = mySuspendPolicy;
+  }
+
+  @Tag("condition")
+  public static class Condition {
+    @Attribute("expression")
+    public String myExpression;
+    @Text
+    public String myOldExpression;
+  }
+
+  @Tag("log-expression")
+  public static class LogExpression {
+    @Attribute("expression")
+    public String myExpression;
+    @Text
+    public String myOldExpression;
+  }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointsFavoriteListProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointsFavoriteListProvider.java
index 03adc64..a2a76c8 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointsFavoriteListProvider.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointsFavoriteListProvider.java
@@ -52,7 +52,6 @@
   private final List<BreakpointPanelProvider> myBreakpointPanelProviders;
   private final BreakpointItemsTreeController myTreeController;
   private final List<XBreakpointGroupingRule> myRulesAvailable = new ArrayList<XBreakpointGroupingRule>();
-  private final BreakpointsSimpleTree myTree;
 
   private Set<XBreakpointGroupingRule> myRulesEnabled = new TreeSet<XBreakpointGroupingRule>(new Comparator<XBreakpointGroupingRule>() {
     @Override
@@ -66,8 +65,7 @@
     super(project, "Breakpoints");
     myBreakpointPanelProviders = XBreakpointUtil.collectPanelProviders();
     myTreeController = new BreakpointItemsTreeController(myRulesAvailable);
-    myTree = new BreakpointsSimpleTree(myProject, myTreeController);
-    myTreeController.setTreeView(myTree);
+    myTreeController.setTreeView(new BreakpointsSimpleTree(myProject, myTreeController));
     updateChildren();
     for (final BreakpointPanelProvider provider : myBreakpointPanelProviders) {
       provider.addListener(this, myProject, myProject);
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java
index aed4f88..f7dff8b 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java
@@ -86,7 +86,10 @@
   public void doUpdateDetailView(DetailView panel, boolean editorOnly) {
     Project project = ((XBreakpointBase)myBreakpoint).getProject();
     //saveState();
-    myPropertiesPanel = null;
+    if (myPropertiesPanel != null) {
+      myPropertiesPanel.dispose();
+      myPropertiesPanel = null;
+    }
     if (!editorOnly) {
       myPropertiesPanel = new XLightBreakpointPropertiesPanel<XBreakpoint<?>>(project, getManager(), myBreakpoint, true);
 
@@ -178,4 +181,10 @@
       return 0;
     }
   }
+
+  public void dispose() {
+    if (myPropertiesPanel != null) {
+      myPropertiesPanel.dispose();
+    }
+  }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java
index eb183f9..233c473 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointManagerImpl.java
@@ -50,6 +50,7 @@
   public static final SkipDefaultValuesSerializationFilters SERIALIZATION_FILTER = new SkipDefaultValuesSerializationFilters();
   private final MultiValuesMap<XBreakpointType, XBreakpointBase<?,?,?>> myBreakpoints = new MultiValuesMap<XBreakpointType, XBreakpointBase<?,?,?>>(true);
   private final Map<XBreakpointType, XBreakpointBase<?,?,?>> myDefaultBreakpoints = new LinkedHashMap<XBreakpointType, XBreakpointBase<?, ?, ?>>();
+  private final Map<XBreakpointType, BreakpointState<?,?,?>> myBreakpointsDefaults = new LinkedHashMap<XBreakpointType, BreakpointState<?, ?, ?>>();
   private final Set<XBreakpointBase<?,?,?>> myAllBreakpoints = new HashSet<XBreakpointBase<?, ?, ?>>();
   private final Map<XBreakpointType, EventDispatcher<XBreakpointListener>> myDispatchers = new HashMap<XBreakpointType, EventDispatcher<XBreakpointListener>>();
   private XBreakpointsDialogState myBreakpointsDialogSettings;
@@ -67,14 +68,16 @@
     myAllBreakpointsDispatcher = EventDispatcher.create(XBreakpointListener.class);
     myDependentBreakpointManager = new XDependentBreakpointManager(this);
     myLineBreakpointManager = new XLineBreakpointManager(project, myDependentBreakpointManager, startupManager);
-    if (!project.isDefault() && !ApplicationManager.getApplication().isUnitTestMode()) {
-      HttpVirtualFileListener httpVirtualFileListener = new HttpVirtualFileListener() {
-        @Override
-        public void fileDownloaded(@NotNull final VirtualFile file) {
-          updateBreakpointInFile(file);
-        }
-      };
-      HttpFileSystem.getInstance().addFileListener(httpVirtualFileListener, project);
+    if (!project.isDefault()) {
+      if (!ApplicationManager.getApplication().isUnitTestMode()) {
+        HttpVirtualFileListener httpVirtualFileListener = new HttpVirtualFileListener() {
+          @Override
+          public void fileDownloaded(@NotNull final VirtualFile file) {
+            updateBreakpointInFile(file);
+          }
+        };
+        HttpFileSystem.getInstance().addFileListener(httpVirtualFileListener, project);
+      }
       for (XBreakpointType<?, ?> type : XBreakpointUtil.getBreakpointTypes()) {
         addDefaultBreakpoint(type);
       }
@@ -127,6 +130,7 @@
     BreakpointState<?,T,?> state = new BreakpointState<XBreakpoint<T>,T,XBreakpointType<XBreakpoint<T>,T>>(enabled,
                                                                                                            type.getId(),
                                                                                                            defaultBreakpoint ? 0 : myTime++);
+    getBreakpointDefaults(type).applyDefaults(state);
     return new XBreakpointBase<XBreakpoint<T>,T, BreakpointState<?,T,?>>(type, this, properties, state);
   }
 
@@ -213,8 +217,11 @@
                                                                                 @Nullable final T properties,
                                                                                 boolean temporary) {
     ApplicationManager.getApplication().assertWriteAccessAllowed();
+    LineBreakpointState<T> state = new LineBreakpointState<T>(true, type.getId(), fileUrl, line, temporary,
+                                                              myTime++);
+    getBreakpointDefaults(type).applyDefaults(state);
     XLineBreakpointImpl<T> breakpoint = new XLineBreakpointImpl<T>(type, this, properties,
-                                                                   new LineBreakpointState<T>(true, type.getId(), fileUrl, line, temporary, myTime++));
+                                                                   state);
     addBreakpoint(breakpoint, false, true);
     return breakpoint;
   }
@@ -353,6 +360,12 @@
       state.getBreakpoints().add(breakpoint.getState());
     }
 
+    for (Map.Entry<XBreakpointType, BreakpointState<?,?,?>> entry : myBreakpointsDefaults.entrySet()) {
+      if (statesAreDifferent(entry.getValue(), createBreakpointDefaults(entry.getKey()))) {
+        state.getBreakpointsDefaults().add(entry.getValue());
+      }
+    }
+
     state.setBreakpointsDialogProperties(myBreakpointsDialogSettings);
     state.setTime(myTime);
     return state;
@@ -366,9 +379,13 @@
     }
 
     BreakpointState defaultState = ((XBreakpointBase)defaultBreakpoint).getState();
-    Element defaultElement = XmlSerializer.serialize(defaultState, SERIALIZATION_FILTER);
-    Element currentElement = XmlSerializer.serialize(state, SERIALIZATION_FILTER);
-    return !JDOMUtil.areElementsEqual(defaultElement, currentElement);
+    return statesAreDifferent(state, defaultState);
+  }
+
+  private static boolean statesAreDifferent(BreakpointState state1, BreakpointState state2) {
+    Element elem1 = XmlSerializer.serialize(state1, SERIALIZATION_FILTER);
+    Element elem2 = XmlSerializer.serialize(state2, SERIALIZATION_FILTER);
+    return !JDOMUtil.areElementsEqual(elem1, elem2);
   }
 
   @Override
@@ -377,6 +394,8 @@
 
     myAllBreakpoints.clear();
     myDefaultBreakpoints.clear();
+    myBreakpointsDefaults.clear();
+
     for (BreakpointState breakpointState : state.getDefaultBreakpoints()) {
       loadBreakpoint(breakpointState, true);
     }
@@ -392,6 +411,12 @@
     for (BreakpointState breakpointState : state.getBreakpoints()) {
       loadBreakpoint(breakpointState, false);
     }
+
+    for (BreakpointState defaults : state.getBreakpointsDefaults()) {
+      XBreakpointType<?,?> type = XBreakpointUtil.findType(defaults.getTypeId());
+      myBreakpointsDefaults.put(type, defaults);
+    }
+
     myDependentBreakpointManager.loadState();
     myLineBreakpointManager.updateBreakpointsUI();
     myTime = state.getTime();
@@ -439,11 +464,26 @@
     return breakpointState.createBreakpoint(type, this);
   }
 
+  public BreakpointState getBreakpointDefaults(XBreakpointType type) {
+    BreakpointState defaultState = myBreakpointsDefaults.get(type);
+    if (defaultState == null) {
+      defaultState = createBreakpointDefaults(type);
+      myBreakpointsDefaults.put(type, defaultState);
+    }
+    return defaultState;
+  }
+
+  private static BreakpointState createBreakpointDefaults(XBreakpointType type) {
+    BreakpointState state = new BreakpointState();
+    state.setTypeId(type.getId());
+    return state;
+  }
 
   @Tag("breakpoint-manager")
   public static class BreakpointManagerState {
     private List<BreakpointState> myDefaultBreakpoints = new ArrayList<BreakpointState>();
     private List<BreakpointState> myBreakpoints = new ArrayList<BreakpointState>();
+    private List<BreakpointState> myBreakpointsDefaults = new ArrayList<BreakpointState>();
     private XBreakpointsDialogState myBreakpointsDialogProperties;
 
     private long myTime;
@@ -461,6 +501,13 @@
       return myBreakpoints;
     }
 
+    @Tag("breakpoints-defaults")
+    @AbstractCollection(surroundWithTag = false,
+                        elementTypes = {BreakpointState.class, LineBreakpointState.class})
+    public List<BreakpointState> getBreakpointsDefaults() {
+      return myBreakpointsDefaults;
+    }
+
     @Tag("breakpoints-dialog")
     public XBreakpointsDialogState getBreakpointsDialogProperties() {
       return myBreakpointsDialogProperties;
@@ -475,6 +522,10 @@
       myDefaultBreakpoints = defaultBreakpoints;
     }
 
+    public void setBreakpointsDefaults(List<BreakpointState> breakpointsDefaults) {
+      myBreakpointsDefaults = breakpointsDefaults;
+    }
+
     public void setBreakpointsDialogProperties(XBreakpointsDialogState breakpointsDialogProperties) {
       myBreakpointsDialogProperties = breakpointsDialogProperties;
     }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java
index 6aae022..07214a6 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java
@@ -23,6 +23,7 @@
 import com.intellij.openapi.editor.colors.EditorColorsManager;
 import com.intellij.openapi.editor.colors.EditorColorsScheme;
 import com.intellij.openapi.editor.ex.MarkupModelEx;
+import com.intellij.openapi.editor.ex.RangeHighlighterEx;
 import com.intellij.openapi.editor.impl.DocumentMarkupModel;
 import com.intellij.openapi.editor.markup.GutterDraggableObject;
 import com.intellij.openapi.editor.markup.RangeHighlighter;
@@ -54,7 +55,7 @@
  * @author nik
  */
 public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreakpointBase<XLineBreakpoint<P>, P, LineBreakpointState<P>> implements XLineBreakpoint<P> {
-  @Nullable private RangeHighlighter myHighlighter;
+  @Nullable private RangeHighlighterEx myHighlighter;
   private final XLineBreakpointType<P> myType;
   private XSourcePosition mySourcePosition;
   private boolean myDisposed;
@@ -86,25 +87,37 @@
     EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
     TextAttributes attributes = scheme.getAttributes(DebuggerColors.BREAKPOINT_ATTRIBUTES);
 
-    RangeHighlighter highlighter = myHighlighter;
-    if (highlighter != null && highlighter.isValid() && document.getLineNumber(highlighter.getStartOffset()) != getLine()) {
+    RangeHighlighterEx highlighter = myHighlighter;
+    if (highlighter != null && (!highlighter.isValid() || document.getLineNumber(highlighter.getStartOffset()) != getLine())) {
       highlighter.dispose();
       myHighlighter = null;
       highlighter = null;
     }
 
+    MarkupModelEx markupModel;
     if (highlighter == null) {
-      MarkupModelEx markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(document, getProject(), true);
+      markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(document, getProject(), true);
       highlighter = markupModel.addPersistentLineHighlighter(getLine(), DebuggerColors.BREAKPOINT_HIGHLIGHTER_LAYER, attributes);
-      if (highlighter != null) {
-        highlighter.setGutterIconRenderer(createGutterIconRenderer());
-        highlighter.putUserData(DebuggerColors.BREAKPOINT_HIGHLIGHTER_KEY, Boolean.TRUE);
-        myHighlighter = highlighter;
+      if (highlighter == null) {
+        return;
       }
+
+      highlighter.setGutterIconRenderer(createGutterIconRenderer());
+      highlighter.putUserData(DebuggerColors.BREAKPOINT_HIGHLIGHTER_KEY, Boolean.TRUE);
+      myHighlighter = highlighter;
+    }
+    else {
+      markupModel = null;
     }
 
-    if (highlighter != null) {
-      updateIcon();
+    updateIcon();
+
+    if (markupModel == null) {
+      markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(document, getProject(), false);
+      if (markupModel != null) {
+        // renderersChanged false — we don't change gutter size
+        markupModel.fireAttributesChanged(highlighter, false);
+      }
     }
   }
 
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsDialog.java
index e438b85..67b0ece 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsDialog.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsDialog.java
@@ -167,7 +167,7 @@
   @NotNull
   @Override
   protected Action[] createActions() {
-    return new Action[]{getOKAction()};
+    return new Action[]{getOKAction(), getHelpAction()};
   }
 
   private class ToggleBreakpointGroupingRuleEnabledAction extends ToggleActionButton {
@@ -380,6 +380,12 @@
     }
   }
 
+  @Nullable
+  @Override
+  protected String getHelpId() {
+    return "reference.dialogs.breakpoints";
+  }
+
   private void saveCurrentItem() {
     ItemWrapper item = myDetailController.getSelectedItem();
     if (item instanceof BreakpointItem) {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/DefaultConditionComboBoxPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/DefaultConditionComboBoxPanel.java
new file mode 100644
index 0000000..9cee406
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/DefaultConditionComboBoxPanel.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xdebugger.impl.breakpoints.ui;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.xdebugger.XSourcePosition;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
+import com.intellij.xdebugger.impl.ui.XDebuggerExpressionComboBox;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * @author egor
+ */
+public class DefaultConditionComboBoxPanel<B extends XBreakpoint<?>> extends XBreakpointCustomPropertiesPanel<B> {
+  private XDebuggerExpressionComboBox myConditionComboBox;
+
+  public DefaultConditionComboBoxPanel(Project project,
+                                       XDebuggerEditorsProvider debuggerEditorsProvider,
+                                       String historyId,
+                                       XSourcePosition sourcePosition) {
+    myConditionComboBox = new XDebuggerExpressionComboBox(project, debuggerEditorsProvider, historyId, sourcePosition);
+  }
+
+  @NotNull
+  @Override
+  public JComponent getComponent() {
+    return myConditionComboBox.getComponent();
+  }
+
+  @Override
+  public void saveTo(@NotNull B breakpoint) {
+    final String condition = StringUtil.nullize(myConditionComboBox.getText(), true);
+    breakpoint.setCondition(condition);
+    if (condition != null) {
+      myConditionComboBox.saveTextInHistory();
+    }
+  }
+
+  @Override
+  public void loadFrom(@NotNull B breakpoint) {
+    myConditionComboBox.setText(StringUtil.notNullize(breakpoint.getCondition()));
+  }
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/DefaultLogExpressionComboBoxPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/DefaultLogExpressionComboBoxPanel.java
new file mode 100644
index 0000000..a4ff954
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/DefaultLogExpressionComboBoxPanel.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xdebugger.impl.breakpoints.ui;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XSourcePosition;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
+import com.intellij.xdebugger.impl.ui.XDebuggerExpressionComboBox;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * @author egor
+ */
+public class DefaultLogExpressionComboBoxPanel<B extends XBreakpoint<?>> extends XBreakpointCustomPropertiesPanel<B> {
+  private XDebuggerExpressionComboBox myLogExpressionComboBox;
+
+  public DefaultLogExpressionComboBoxPanel(Project project,
+                                           XDebuggerEditorsProvider debuggerEditorsProvider,
+                                           String historyId,
+                                           XSourcePosition sourcePosition) {
+    myLogExpressionComboBox = new XDebuggerExpressionComboBox(project, debuggerEditorsProvider, historyId, sourcePosition);
+  }
+
+  @NotNull
+  @Override
+  public JComponent getComponent() {
+    return myLogExpressionComboBox.getComponent();
+  }
+
+  @Override
+  public void saveTo(@NotNull B breakpoint) {
+    String logExpression = myLogExpressionComboBox.getComponent().isEnabled() ? myLogExpressionComboBox.getText() : null;
+    breakpoint.setLogExpression(logExpression);
+    myLogExpressionComboBox.saveTextInHistory();
+  }
+
+  @Override
+  public void loadFrom(@NotNull B breakpoint) {
+    String logExpression = breakpoint.getLogExpression();
+    myLogExpressionComboBox.setText(logExpression != null ? logExpression : "");
+  }
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java
index 26049ac..2ccff41 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java
@@ -19,9 +19,9 @@
 import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.intellij.xdebugger.breakpoints.XBreakpointManager;
 import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
 import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
 import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
-import com.intellij.xdebugger.impl.ui.XDebuggerExpressionComboBox;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -44,7 +44,7 @@
   private JPanel myContentPane;
   private JPanel myMainPanel;
   private JCheckBox myTemporaryCheckBox;
-  private XDebuggerExpressionComboBox myLogExpressionComboBox;
+  XBreakpointCustomPropertiesPanel<B> logExpressionPanel;
 
   public void init(Project project, XBreakpointManager breakpointManager, @NotNull B breakpoint, @Nullable XDebuggerEditorsProvider debuggerEditorsProvider) {
     init(project, breakpointManager, breakpoint);
@@ -55,10 +55,18 @@
         }
       };
 
-      myLogExpressionComboBox = new XDebuggerExpressionComboBox(project, debuggerEditorsProvider, "breakpointLogExpression", myBreakpoint.getSourcePosition());
-      JComponent logExpressionComponent = myLogExpressionComboBox.getComponent();
+      if (debuggerEditorsProvider instanceof XDebuggerComboBoxProvider) {
+        logExpressionPanel = ((XDebuggerComboBoxProvider<B>)debuggerEditorsProvider).createLogExpressionComboBoxPanel(
+          project, debuggerEditorsProvider, "breakpointCondition", myBreakpoint.getSourcePosition());
+      }
+      else {
+        logExpressionPanel =
+          new DefaultLogExpressionComboBoxPanel<B>(project, debuggerEditorsProvider, "breakpointCondition", myBreakpoint.getSourcePosition());
+      }
+
+      JComponent logExpressionComponent = logExpressionPanel.getComponent();
       myLogExpressionPanel.add(logExpressionComponent, BorderLayout.CENTER);
-      myLogExpressionComboBox.setEnabled(false);
+      logExpressionComponent.setEnabled(false);
       myTemporaryCheckBox.setVisible(breakpoint instanceof XLineBreakpoint);
       myLogExpressionCheckBox.addActionListener(listener);
       DebuggerUIUtil.focusEditorOnCheck(myLogExpressionCheckBox, logExpressionComponent);
@@ -81,8 +89,8 @@
   }
 
   private void onCheckboxChanged() {
-    if (myLogExpressionComboBox != null) {
-      myLogExpressionComboBox.setEnabled(myLogExpressionCheckBox.isSelected());
+    if (logExpressionPanel != null) {
+      logExpressionPanel.getComponent().setEnabled(myLogExpressionCheckBox.isSelected());
     }
   }
 
@@ -94,10 +102,9 @@
       myTemporaryCheckBox.setSelected(((XLineBreakpoint)myBreakpoint).isTemporary());
     }
 
-    if (myLogExpressionComboBox != null) {
-      String logExpression = myBreakpoint.getLogExpression();
-      myLogExpressionCheckBox.setSelected(logExpression != null);
-      myLogExpressionComboBox.setText(logExpression != null ? logExpression : "");
+    if (logExpressionPanel != null) {
+      myLogExpressionCheckBox.setSelected(myBreakpoint.getLogExpression() != null);
+      logExpressionPanel.loadFrom(myBreakpoint);
     }
     onCheckboxChanged();
   }
@@ -110,11 +117,14 @@
       ((XLineBreakpoint)myBreakpoint).setTemporary(myTemporaryCheckBox.isSelected());
     }
 
-    if (myLogExpressionComboBox != null) {
-      String logExpression = myLogExpressionCheckBox.isSelected() ? myLogExpressionComboBox.getText() : null;
-      myBreakpoint.setLogExpression(logExpression);
-      myLogExpressionComboBox.saveTextInHistory();
+    if (logExpressionPanel != null) {
+      logExpressionPanel.saveTo(myBreakpoint);
     }
+  }
 
+  public void dispose() {
+    if (logExpressionPanel != null) {
+      logExpressionPanel.dispose();
+    }
   }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XDebuggerComboBoxProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XDebuggerComboBoxProvider.java
new file mode 100644
index 0000000..fd53911
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XDebuggerComboBoxProvider.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xdebugger.impl.breakpoints.ui;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.xdebugger.XSourcePosition;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
+
+/**
+ * @author egor
+ */
+public interface XDebuggerComboBoxProvider<B extends XBreakpoint<?>> {
+  XBreakpointCustomPropertiesPanel<B> createConditionComboBoxPanel(Project project,
+                                                                             XDebuggerEditorsProvider debuggerEditorsProvider,
+                                                                             String historyId,
+                                                                             XSourcePosition sourcePosition);
+
+  XBreakpointCustomPropertiesPanel<B> createLogExpressionComboBoxPanel(Project project,
+                                                                                XDebuggerEditorsProvider debuggerEditorsProvider,
+                                                                                String historyId,
+                                                                                XSourcePosition sourcePosition);
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java
index bc6d5e4..7c91083 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java
@@ -16,7 +16,6 @@
 package com.intellij.xdebugger.impl.breakpoints.ui;
 
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.wm.IdeFocusManager;
 import com.intellij.ui.popup.util.DetailView;
 import com.intellij.xdebugger.breakpoints.XBreakpoint;
@@ -26,7 +25,6 @@
 import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
 import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase;
 import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil;
-import com.intellij.xdebugger.impl.ui.XDebuggerExpressionComboBox;
 
 import javax.swing.*;
 import java.awt.*;
@@ -83,8 +81,6 @@
 
   private List<XBreakpointPropertiesSubPanel<B>> mySubPanels = new ArrayList<XBreakpointPropertiesSubPanel<B>>();
 
-  private XDebuggerExpressionComboBox myConditionComboBox;
-
   private B myBreakpoint;
 
   public void setDetailView(DetailView detailView) {
@@ -106,10 +102,25 @@
     myActionsPanel.init(project, breakpointManager, breakpoint, debuggerEditorsProvider);
     mySubPanels.add(myActionsPanel);
 
+    myCustomPanels = new ArrayList<XBreakpointCustomPropertiesPanel<B>>();
     if (debuggerEditorsProvider != null) {
-      myConditionComboBox = new XDebuggerExpressionComboBox(project, debuggerEditorsProvider, "breakpointCondition", myBreakpoint.getSourcePosition());
-      JComponent conditionComponent = myConditionComboBox.getComponent();
-      myConditionExpressionPanel.add(conditionComponent, BorderLayout.CENTER);
+      final XBreakpointCustomPropertiesPanel<B> conditionPanel;
+      if (debuggerEditorsProvider instanceof XDebuggerComboBoxProvider) {
+        conditionPanel = ((XDebuggerComboBoxProvider<B>)debuggerEditorsProvider).createConditionComboBoxPanel(
+            project, debuggerEditorsProvider, "breakpointCondition", myBreakpoint.getSourcePosition());
+      }
+      else {
+        conditionPanel =
+          new DefaultConditionComboBoxPanel<B>(project, debuggerEditorsProvider, "breakpointCondition", myBreakpoint.getSourcePosition());
+      }
+      myConditionExpressionPanel.add(conditionPanel.getComponent(), BorderLayout.CENTER);
+      myCustomPanels.add(conditionPanel);
+      myMainPanel.addFocusListener(new FocusAdapter() {
+        @Override
+        public void focusGained(FocusEvent event) {
+          IdeFocusManager.findInstance().requestFocus(conditionPanel.getComponent(), false);
+        }
+      });
     } else {
       myConditionPanel.setVisible(false);
     }
@@ -121,7 +132,6 @@
       }
     }
 
-    myCustomPanels = new ArrayList<XBreakpointCustomPropertiesPanel<B>>();
     XBreakpointCustomPropertiesPanel<B> customPropertiesPanel = breakpointType.createCustomPropertiesPanel();
     if (customPropertiesPanel != null) {
       myCustomPropertiesPanelWrapper.add(customPropertiesPanel.getComponent(), BorderLayout.CENTER);
@@ -140,14 +150,6 @@
       myCustomPanels.add(customRightConditionPanel);
     }
 
-    myMainPanel.addFocusListener(new FocusAdapter() {
-      @Override
-      public void focusGained(FocusEvent event) {
-        if (myConditionComboBox != null) {
-          IdeFocusManager.findInstance().requestFocus(myConditionComboBox.getComponent(), false);
-        }
-      }
-    });
     myEnabledCheckbox.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent event) {
@@ -161,14 +163,6 @@
       panel.saveProperties();
     }
 
-    if (myConditionComboBox != null) {
-      final String condition = StringUtil.nullize(myConditionComboBox.getText(), true);
-      myBreakpoint.setCondition(condition);
-      if (condition != null) {
-        myConditionComboBox.saveTextInHistory();
-      }
-    }
-
     for (XBreakpointCustomPropertiesPanel<B> customPanel : myCustomPanels) {
       customPanel.saveTo(myBreakpoint);
     }
@@ -183,10 +177,6 @@
       panel.loadProperties();
     }
     
-    if (myConditionComboBox != null) {
-      myConditionComboBox.setText(StringUtil.notNullize(myBreakpoint.getCondition()));
-    }
-
     for (XBreakpointCustomPropertiesPanel<B> customPanel : myCustomPanels) {
       customPanel.loadFrom(myBreakpoint);
     }
@@ -197,4 +187,11 @@
   public JPanel getMainPanel() {
     return myMainPanel;
   }
+
+  public void dispose() {
+    myActionsPanel.dispose();
+    for (XBreakpointCustomPropertiesPanel<B> panel : myCustomPanels) {
+      panel.dispose();
+    }
+  }
 }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XSuspendPolicyPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XSuspendPolicyPanel.java
index c46914f..b3dcd13 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XSuspendPolicyPanel.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XSuspendPolicyPanel.java
@@ -15,11 +15,11 @@
  */
 package com.intellij.xdebugger.impl.breakpoints.ui;
 
-import com.intellij.ide.util.PropertiesComponent;
 import com.intellij.openapi.project.Project;
 import com.intellij.xdebugger.breakpoints.SuspendPolicy;
 import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.intellij.xdebugger.breakpoints.XBreakpointManager;
+import com.intellij.xdebugger.impl.breakpoints.XBreakpointManagerImpl;
 import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
@@ -72,7 +72,7 @@
     mySuspendPolicyGroup.add(mySuspendAll);
     mySuspendPolicyGroup.add(mySuspendThread);
 
-    updateSuspendPolicyFont(createSettingsKey());
+    updateSuspendPolicyFont();
 
     ItemListener suspendPolicyChangeListener = new ItemListener() {
       @Override
@@ -89,9 +89,8 @@
       @Override
       public void actionPerformed(ActionEvent e) {
         SuspendPolicy suspendPolicy = getSelectedSuspendPolicy();
-        String settingsKey = createSettingsKey();
-        PropertiesComponent.getInstance().setValue(settingsKey, suspendPolicy.name());
-        updateSuspendPolicyFont(settingsKey);
+        ((XBreakpointManagerImpl)myBreakpointManager).getBreakpointDefaults(myBreakpointType).setSuspendPolicy(suspendPolicy);
+        updateSuspendPolicyFont();
         if (SuspendPolicy.THREAD == suspendPolicy) {
           mySuspendThread.requestFocus();
         }
@@ -104,20 +103,16 @@
   }
 
   private void updateMakeDefaultEnableState() {
-    myMakeDefaultButton.setEnabled(!getSelectedSuspendPolicy().name().equalsIgnoreCase(PropertiesComponent.getInstance().getValue(createSettingsKey(), SuspendPolicy.ALL.name())));
+    myMakeDefaultButton.setEnabled(!getSelectedSuspendPolicy().equals(((XBreakpointManagerImpl)myBreakpointManager).getBreakpointDefaults(myBreakpointType).getSuspendPolicy()));
   }
 
-  private String createSettingsKey() {
-    return "debugger.suspend.policy-" + myBreakpointType.getId();
-  }
-
-  private void updateSuspendPolicyFont(String settingsKey) {
-    String defaultPolicy = PropertiesComponent.getInstance().getValue(settingsKey, SuspendPolicy.ALL.name());
+  private void updateSuspendPolicyFont() {
+    SuspendPolicy defaultPolicy = ((XBreakpointManagerImpl)myBreakpointManager).getBreakpointDefaults(myBreakpointType).getSuspendPolicy();
     Font font = mySuspendAll.getFont().deriveFont(Font.PLAIN);
     Font boldFont = font.deriveFont(Font.BOLD);
 
-    mySuspendAll.setFont(SuspendPolicy.ALL.name().equalsIgnoreCase(defaultPolicy) ? boldFont : font);
-    mySuspendThread.setFont(SuspendPolicy.THREAD.name().equalsIgnoreCase(defaultPolicy) ? boldFont : font);
+    mySuspendAll.setFont(SuspendPolicy.ALL.equals(defaultPolicy) ? boldFont : font);
+    mySuspendThread.setFont(SuspendPolicy.THREAD.equals(defaultPolicy) ? boldFont : font);
   }
 
   private void changeEnableState(boolean selected) {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointTypeGroup.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointTypeGroup.java
index d00e274..c000539 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointTypeGroup.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointTypeGroup.java
@@ -17,6 +17,8 @@
 
 import com.intellij.util.ArrayUtil;
 import com.intellij.xdebugger.breakpoints.XBreakpointType;
+import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.intellij.xdebugger.breakpoints.XLineBreakpointType;
 import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup;
 import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil;
 import org.jetbrains.annotations.NotNull;
@@ -49,6 +51,22 @@
   @Override
   public int compareTo(XBreakpointGroup o) {
     if (o instanceof XBreakpointTypeGroup) {
+      if (((XBreakpointTypeGroup)o).myBreakpointType instanceof XLineBreakpointType) {
+        if (myBreakpointType instanceof XLineBreakpointType) {
+          int res = ((XLineBreakpointType)((XBreakpointTypeGroup)o).myBreakpointType).getPriority() -
+                  ((XLineBreakpointType)myBreakpointType).getPriority();
+          if (res != 0) {
+            return res;
+          }
+        }
+        else {
+          // line breakpoints should be on top
+          return 1;
+        }
+      }
+      else if (myBreakpointType instanceof XLineBreakpointType) {
+        return -1;
+      }
       return indexOfType(myBreakpointType) - indexOfType(((XBreakpointTypeGroup)o).getBreakpointType());
     }
     return -o.compareTo(this);
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemsTreeController.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemsTreeController.java
index babdd09..7c90280 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemsTreeController.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemsTreeController.java
@@ -43,7 +43,6 @@
   private final CheckedTreeNode myRoot;
   private final Map<BreakpointItem, BreakpointItemNode> myNodes = new HashMap<BreakpointItem, BreakpointItemNode>();
   private List<XBreakpointGroupingRule> myGroupingRules;
-  private final Map<XBreakpointGroup, BreakpointsGroupNode> myGroupNodes = new HashMap<XBreakpointGroup, BreakpointsGroupNode>();
 
   private final MultiValuesMap<XBreakpointGroupingRule, XBreakpointGroup> myGroups = new MultiValuesMap<XBreakpointGroupingRule, XBreakpointGroup>();
 
@@ -110,7 +109,6 @@
     final TreeState state = TreeState.createOn(myTreeView, myRoot);
     myRoot.removeAllChildren();
     myNodes.clear();
-    myGroupNodes.clear();
     myGroups.clear();
     for (BreakpointItem breakpoint : breakpoints) {
       BreakpointItemNode node = new BreakpointItemNode(breakpoint);
@@ -130,53 +128,42 @@
   @NotNull
   private CheckedTreeNode getParentNode(final BreakpointItem breakpoint) {
     CheckedTreeNode parent = myRoot;
-    XBreakpointGroup parentGroup = null;
     for (int i = 0; i < myGroupingRules.size(); i++) {
-      XBreakpointGroup group = getGroup(parentGroup, breakpoint, myGroupingRules.get(i));
+      Collection<XBreakpointGroup> existingGroups = getGroupNodes(parent);
+      XBreakpointGroup group = myGroupingRules.get(i).getGroup(breakpoint.getBreakpoint(), existingGroups);
       if (group != null) {
         parent = getOrCreateGroupNode(parent, group, i);
-        parentGroup = group;
       }
     }
     return parent;
   }
 
-  @Nullable
-  private XBreakpointGroup getGroup(XBreakpointGroup parentGroup, final BreakpointItem breakpoint, final XBreakpointGroupingRule groupingRule) {
-    //noinspection unchecked
-    Collection<XBreakpointGroup> groups = myGroups.get(groupingRule);
-    if (groups == null) {
-      groups = Collections.emptyList();
-    }
-
-    XBreakpointGroup group = groupingRule.getGroup(breakpoint.getBreakpoint(), filterByParent(parentGroup, groups));
-    if (group != null) {
-      myGroups.put(groupingRule, group);
-    }
-    return group;
-  }
-
-  private Collection<XBreakpointGroup> filterByParent(XBreakpointGroup parentGroup, Collection<XBreakpointGroup> groups) {
-    Collection<XBreakpointGroup> filtered = new ArrayList<XBreakpointGroup>();
-    for (XBreakpointGroup group : groups) {
-      TreeNode parentNode = myGroupNodes.get(group).getParent();
-      BreakpointsGroupNode parent = parentNode instanceof BreakpointsGroupNode ? (BreakpointsGroupNode)parentNode : null;
-      if ((parentGroup == null && parentNode == myRoot) || (parent != null && parent.getGroup() == parentGroup)) {
-        filtered.add(group);
+  private static Collection<XBreakpointGroup> getGroupNodes(CheckedTreeNode parent) {
+    Collection<XBreakpointGroup> nodes = new ArrayList<XBreakpointGroup>();
+    Enumeration children = parent.children();
+    while (children.hasMoreElements()) {
+      Object element = children.nextElement();
+      if (element instanceof BreakpointsGroupNode) {
+        nodes.add(((BreakpointsGroupNode)element).getGroup());
       }
     }
-    return filtered;
+    return nodes;
   }
 
-  private <G extends XBreakpointGroup> BreakpointsGroupNode<G> getOrCreateGroupNode(CheckedTreeNode parent, final G group,
+  private static BreakpointsGroupNode getOrCreateGroupNode(CheckedTreeNode parent, final XBreakpointGroup group,
                                                                                        final int level) {
-    //noinspection unchecked
-    BreakpointsGroupNode<G> groupNode = (BreakpointsGroupNode<G>)myGroupNodes.get(group);
-    if (groupNode == null) {
-      groupNode = new BreakpointsGroupNode<G>(group, level);
-      myGroupNodes.put(group, groupNode);
-      parent.add(groupNode);
+    Enumeration children = parent.children();
+    while (children.hasMoreElements()) {
+      Object element = children.nextElement();
+      if (element instanceof BreakpointsGroupNode) {
+        XBreakpointGroup groupFound = ((BreakpointsGroupNode)element).getGroup();
+        if (groupFound.equals(group)) {
+          return (BreakpointsGroupNode)element;
+        }
+      }
     }
+    BreakpointsGroupNode groupNode = new BreakpointsGroupNode<XBreakpointGroup>(group, level);
+    parent.add(groupNode);
     return groupNode;
   }
 
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java
index 741b287..4abf173 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java
@@ -29,7 +29,6 @@
 import com.intellij.xdebugger.evaluation.EvaluationMode;
 import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
 import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
-import com.intellij.xdebugger.frame.XStackFrame;
 import com.intellij.xdebugger.impl.XDebugSessionImpl;
 import com.intellij.xdebugger.impl.actions.XDebuggerActions;
 import com.intellij.xdebugger.impl.ui.XDebuggerEditorBase;
@@ -38,6 +37,7 @@
 import com.intellij.xdebugger.impl.ui.tree.nodes.EvaluatingExpressionRootNode;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.awt.*;
@@ -61,10 +61,10 @@
   private final boolean myIsCodeFragmentEvaluationSupported;
 
   public XDebuggerEvaluationDialog(@NotNull XDebugSession session,
-                                   final @NotNull XDebuggerEditorsProvider editorsProvider,
+                                   @NotNull XDebuggerEditorsProvider editorsProvider,
                                    @NotNull XDebuggerEvaluator evaluator,
                                    @NotNull String text,
-                                   final XSourcePosition sourcePosition) {
+                                   @Nullable XSourcePosition sourcePosition) {
     super(session.getProject(), true);
     mySession = session;
     myEditorsProvider = editorsProvider;
@@ -212,8 +212,7 @@
     inputEditor.saveTextInHistory();
     String expression = inputEditor.getText();
 
-    XStackFrame frame = mySession.getCurrentStackFrame();
-    XDebuggerEvaluator evaluator = frame == null ? null : frame.getEvaluator();
+    XDebuggerEvaluator evaluator = mySession.getDebugProcess().getEvaluator();
     if (evaluator == null) {
       evaluationCallback.errorOccurred(XDebuggerBundle.message("xdebugger.evaluate.stack.frame.has.not.evaluator"));
     }
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java
index 8813e70..81e94ff 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java
@@ -26,7 +26,6 @@
 import com.intellij.xdebugger.XDebugSession;
 import com.intellij.xdebugger.XDebuggerManager;
 import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
-import com.intellij.xdebugger.frame.XStackFrame;
 import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint;
 import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler;
 import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType;
@@ -44,11 +43,7 @@
   @Override
   public boolean isEnabled(@NotNull final Project project) {
     XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
-    if (session == null || !session.isSuspended()) {
-      return false;
-    }
-    XStackFrame stackFrame = session.getCurrentStackFrame();
-    return stackFrame != null && stackFrame.getEvaluator() != null;
+    return session != null && session.getDebugProcess().getEvaluator() != null;
   }
 
   @Override
@@ -58,11 +53,7 @@
       return null;
     }
 
-    XStackFrame stackFrame = session.getCurrentStackFrame();
-    if (stackFrame == null) {
-      return null;
-    }
-    final XDebuggerEvaluator evaluator = stackFrame.getEvaluator();
+    final XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator();
     if (evaluator == null) {
       return null;
     }
@@ -111,12 +102,9 @@
   public int getValueLookupDelay(final Project project) {
     XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
     if (session != null) {
-      XStackFrame stackFrame = session.getCurrentStackFrame();
-      if (stackFrame != null) {
-        XDebuggerEvaluator evaluator = stackFrame.getEvaluator();
-        if (evaluator != null) {
-          return evaluator.getValuePopupDelay();
-        }
+      XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator();
+      if (evaluator != null) {
+        return evaluator.getValuePopupDelay();
       }
     }
     return 700;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java
index 415742b..ebf5d69 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java
@@ -16,6 +16,10 @@
 package com.intellij.xdebugger.impl.evaluate.quick;
 
 import com.intellij.codeInsight.hint.HintUtil;
+import com.intellij.execution.console.LanguageConsoleImpl;
+import com.intellij.execution.console.LanguageConsoleView;
+import com.intellij.execution.impl.ConsoleViewImpl;
+import com.intellij.execution.ui.ConsoleView;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -72,7 +76,17 @@
     myEvaluator = evaluator;
     myDebugSession = session;
     myExpression = XDebuggerEvaluateActionHandler.getExpressionText(expressionData, editor.getDocument());
-    final VirtualFile file = FileDocumentManager.getInstance().getFile(editor.getDocument());
+
+    VirtualFile file;
+    ConsoleView consoleView = ConsoleViewImpl.CONSOLE_VIEW_IN_EDITOR_VIEW.get(editor);
+    if (consoleView instanceof LanguageConsoleView) {
+      LanguageConsoleImpl console = ((LanguageConsoleView)consoleView).getConsole();
+      file = console.getHistoryViewer() == editor ? console.getVirtualFile() : null;
+    }
+    else {
+      file = FileDocumentManager.getInstance().getFile(editor.getDocument());
+    }
+
     myExpressionPosition = file != null ? XDebuggerUtil.getInstance().createPositionByOffset(file, expressionData.first.getStartOffset()) : null;
   }
 
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/ValueLookupManager.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/ValueLookupManager.java
index cd1cfe2..13facc0 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/ValueLookupManager.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/ValueLookupManager.java
@@ -29,6 +29,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.util.Alarm;
 import com.intellij.xdebugger.impl.DebuggerSupport;
+import org.jetbrains.annotations.NotNull;
 
 import java.awt.*;
 
@@ -107,7 +108,7 @@
     }
   }
 
-  public void showHint(final QuickEvaluateHandler handler, Editor editor, Point point, ValueHintType type) {
+  public void showHint(@NotNull QuickEvaluateHandler handler, @NotNull Editor editor, @NotNull Point point, @NotNull ValueHintType type) {
     myAlarm.cancelAllRequests();
     if (editor.isDisposed() || !handler.canShowHint(myProject)) {
       return;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java
index 48defd3..088b400 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java
@@ -123,8 +123,7 @@
 
   @Override
   public void addWatchExpression(@NotNull String expression, int index, final boolean navigateToWatchNode) {
-    XStackFrame stackFrame = mySession.getCurrentStackFrame();
-    myRootNode.addWatchExpression(stackFrame == null ? null : stackFrame.getEvaluator(), expression, index, navigateToWatchNode);
+    myRootNode.addWatchExpression(mySession.getDebugProcess().getEvaluator(), expression, index, navigateToWatchNode);
     updateSessionData();
   }
 
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java
index abce43b..d09bc7f 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java
@@ -141,6 +141,7 @@
 
     final Ref<Balloon> balloonRef = Ref.create(null);
     final Ref<Boolean> isLoading = Ref.create(Boolean.FALSE);
+    final Ref<Boolean> moreOptionsRequested = Ref.create(Boolean.FALSE);
 
     propertiesPanel.setDelegate(new XLightBreakpointPropertiesPanel.Delegate() {
       @Override
@@ -152,6 +153,7 @@
           balloonRef.get().hide();
         }
         showXBreakpointEditorBalloon(project, point, component, true, breakpoint);
+        moreOptionsRequested.set(true);
       }
     });
 
@@ -159,10 +161,15 @@
     propertiesPanel.loadProperties();
     isLoading.set(Boolean.FALSE);
 
+    if (moreOptionsRequested.get()) {
+      return;
+    }
+
     Runnable showMoreOptions = new Runnable() {
       @Override
       public void run() {
         propertiesPanel.saveProperties();
+        propertiesPanel.dispose();
         BreakpointsDialogFactory.getInstance(project).showDialog(breakpoint);
       }
     };
@@ -184,6 +191,7 @@
       @Override
       public void onClosed(LightweightWindowEvent event) {
         propertiesPanel.saveProperties();
+        propertiesPanel.dispose();
         breakpointManager.removeBreakpointListener(breakpointListener);
       }
     });
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java
index 47485e5..db7aef7 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java
@@ -72,7 +72,7 @@
 
   public void navigateTo() {
     if (myOpenFileDescriptor != null) {
-      FileEditorManager.getInstance(myProject).openTextEditor(myOpenFileDescriptor, false);
+      FileEditorManager.getInstance(myProject).openTextEditor(myOpenFileDescriptor, true);
     }
   }
 
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
index e442654..1aa9e2c 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
@@ -144,6 +144,9 @@
         if (XWatchesView.DATA_KEY.is(dataId)) {
           return myWatchesView;
         }
+        if (LangDataKeys.CONSOLE_VIEW.is(dataId)) {
+          return session.getConsoleView();
+        }
         return null;
       }
     });
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/EvaluateInConsoleFromTreeAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/EvaluateInConsoleFromTreeAction.java
new file mode 100644
index 0000000..5bff527
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/EvaluateInConsoleFromTreeAction.java
@@ -0,0 +1,32 @@
+package com.intellij.xdebugger.impl.ui.tree.actions;
+
+import com.intellij.execution.console.ConsoleExecuteAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.xdebugger.impl.actions.handlers.XEvaluateInConsoleFromEditorActionHandler;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+class EvaluateInConsoleFromTreeAction extends XAddToWatchesAction {
+  @Override
+  protected boolean isEnabled(@NotNull XValueNodeImpl node, @NotNull AnActionEvent e) {
+    return super.isEnabled(node, e) && getConsoleExecuteAction(e) != null;
+  }
+
+  @Nullable
+  private static ConsoleExecuteAction getConsoleExecuteAction(@NotNull AnActionEvent e) {
+    return XEvaluateInConsoleFromEditorActionHandler.getConsoleExecuteAction(e.getData(LangDataKeys.CONSOLE_VIEW));
+  }
+
+  @Override
+  protected void perform(XValueNodeImpl node, @NotNull String nodeName, AnActionEvent e) {
+    ConsoleExecuteAction action = getConsoleExecuteAction(e);
+    if (action != null) {
+      String expression = node.getValueContainer().getEvaluationExpression();
+      if (expression != null) {
+        action.execute(null, expression, null);
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java
index a3621cb..eb6c158 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java
@@ -21,9 +21,9 @@
 import org.jetbrains.annotations.NotNull;
 
 /**
- * @author nik
+ * This action works only in the variables view, it is not generic action like {@see com.intellij.xdebugger.impl.actions.AddToWatchesAction}
  */
-public class XAddToWatchesAction extends XDebuggerTreeActionBase {
+class XAddToWatchesAction extends XDebuggerTreeActionBase {
   @Override
   protected boolean isEnabled(@NotNull final XValueNodeImpl node, @NotNull AnActionEvent e) {
     return super.isEnabled(node, e) && node.getValueContainer().getEvaluationExpression() != null && e.getData(XWatchesView.DATA_KEY) != null;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java
index 379b07c..1833ae3 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java
@@ -44,7 +44,7 @@
 
   public static class EvaluatingResultContainer extends XValueContainer implements XDebuggerTreeListener {
     private final XDebuggerEvaluationDialog myDialog;
-    private XDebuggerTree myTree;
+    private final XDebuggerTree myTree;
 
     public EvaluatingResultContainer(final XDebuggerEvaluationDialog dialog, XDebuggerTree tree) {
       myDialog = dialog;
diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java
index 38e9154..a4cd467 100644
--- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java
+++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XBreakpointManagerTest.java
@@ -32,23 +32,26 @@
 public class XBreakpointManagerTest extends XBreakpointsTestCase {
 
   public void testAddRemove() {
+    XBreakpoint<MyBreakpointProperties> defaultBreakpoint = myBreakpointManager.getDefaultBreakpoint(MY_SIMPLE_BREAKPOINT_TYPE);
+    assertSameElements(getAllBreakpoints(), defaultBreakpoint);
+
     XLineBreakpoint<MyBreakpointProperties> lineBreakpoint =
       myBreakpointManager.addLineBreakpoint(MY_LINE_BREAKPOINT_TYPE, "url", 239, new MyBreakpointProperties("123"));
 
     XBreakpoint<MyBreakpointProperties> breakpoint = myBreakpointManager.addBreakpoint(MY_SIMPLE_BREAKPOINT_TYPE, new MyBreakpointProperties("abc"));
 
-    assertSameElements(getAllBreakpoints(), breakpoint, lineBreakpoint);
+    assertSameElements(getAllBreakpoints(), breakpoint, lineBreakpoint, defaultBreakpoint);
     assertSame(lineBreakpoint, assertOneElement(myBreakpointManager.getBreakpoints(MY_LINE_BREAKPOINT_TYPE)));
-    assertSame(breakpoint, getSingleBreakpoint());
+    assertSameElements(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE), breakpoint, defaultBreakpoint);
 
     myBreakpointManager.removeBreakpoint(lineBreakpoint);
-    assertSame(breakpoint, assertOneElement(getAllBreakpoints()));
+    assertSameElements(getAllBreakpoints(), breakpoint, defaultBreakpoint);
     assertTrue(myBreakpointManager.getBreakpoints(MY_LINE_BREAKPOINT_TYPE).isEmpty());
-    assertSame(breakpoint, getSingleBreakpoint());
+    assertSameElements(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE), breakpoint, defaultBreakpoint);
 
     myBreakpointManager.removeBreakpoint(breakpoint);
-    assertEmpty(getAllBreakpoints());
-    assertTrue(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE).isEmpty());
+    assertSameElements(getAllBreakpoints(), defaultBreakpoint);
+    assertSameElements(myBreakpointManager.getBreakpoints(MY_SIMPLE_BREAKPOINT_TYPE), defaultBreakpoint);
   }
 
   public void testSerialize() {
diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java
index 3e4067f..0f140e3 100644
--- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java
+++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java
@@ -65,7 +65,8 @@
     XBreakpointManager manager = XDebuggerManager.getInstance(project).getBreakpointManager();
     XLineBreakpointImpl breakpoint = (XLineBreakpointImpl)manager.findBreakpointAtLine(type, file, line);
     Assert.assertNotNull(breakpoint);
-    Assert.assertEquals(validity ? AllIcons.Debugger.Db_verified_breakpoint : AllIcons.Debugger.Db_invalid_breakpoint, breakpoint.getIcon());
+    Assert
+      .assertEquals(validity ? AllIcons.Debugger.Db_verified_breakpoint : AllIcons.Debugger.Db_invalid_breakpoint, breakpoint.getIcon());
     Assert.assertEquals(errorMessage, breakpoint.getErrorMessage());
   }
 
@@ -303,7 +304,8 @@
     expectedNames.removeAll(actualNames);
     UsefulTestCase.assertTrue("Missing variables:" + StringUtil.join(expectedNames, ", ")
                               + "\nAll Variables: " + StringUtil.join(actualNames, ", "),
-                              expectedNames.isEmpty());
+                              expectedNames.isEmpty()
+    );
   }
 
   public static void assertSourcePosition(final XValue value, VirtualFile file, int offset) {
@@ -366,8 +368,23 @@
   public static void removeAllBreakpoints(@NotNull final Project project) {
     final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager();
     XBreakpoint<?>[] breakpoints = breakpointManager.getAllBreakpoints();
-    for (XBreakpoint b : breakpoints) {
-      breakpointManager.removeBreakpoint(b);
+    for (final XBreakpoint b : breakpoints) {
+      new WriteAction() {
+        @Override
+        protected void run(Result result) throws Throwable {
+          breakpointManager.removeBreakpoint(b);
+        }
+      }.execute();
+    }
+  }
+
+  public static <B extends XBreakpoint<?>>
+  void setDefaultBreakpointEnabled(@NotNull final Project project, Class<? extends XBreakpointType<B, ?>> bpTypeClass, boolean enabled) {
+    final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager();
+    XBreakpointType<B, ?> bpType = XDebuggerUtil.getInstance().findBreakpointType(bpTypeClass);
+    XBreakpoint<?> bp = breakpointManager.getDefaultBreakpoint(bpType);
+    if (bp != null) {
+      bp.setEnabled(enabled);
     }
   }
 
diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGroupVirtualFile.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGroupVirtualFile.java
index c44b49c..069ef03 100644
--- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGroupVirtualFile.java
+++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGroupVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -43,7 +43,7 @@
   @Override
   public String getName() {
     final String prefix = StringUtil.commonPrefix(myBeforeFile.getName(), myAfterFile.getName());
-    if (prefix.length() == 0) {
+    if (prefix.isEmpty()) {
       return StringUtil.commonSuffix(myBeforeFile.getName(), myAfterFile.getName());
     }
     return prefix + "." + myBeforeFile.getExtension();
@@ -63,6 +63,7 @@
     return LocalFileSystem.getInstance();
   }
 
+  @NotNull
   @Override
   public String getPath() {
     return myBeforeFile.getPath();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
index dddb6e1..4becc97 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
@@ -2489,6 +2489,9 @@
     <localInspection language="JAVA" suppressId="LockAcquiredButNotSafelyReleased" shortName="SafeLock" bundle="com.siyeh.InspectionGadgetsBundle"
                      key="safe.lock.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.threading.issues"
                      enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.threading.SafeLockInspection"/>
+    <localInspection language="JAVA" suppressId="SharedThreadLocalRandom" shortName="SharedThreadLocalRandom" bundle="com.siyeh.InspectionGadgetsBundle"
+                     key="shared.thread.local.random.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.threading.issues"
+                     enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.threading.SharedThreadLocalRandomInspection"/>
     <localInspection language="JAVA" shortName="SignalWithoutCorrespondingAwait" bundle="com.siyeh.InspectionGadgetsBundle"
                      key="signal.without.corresponding.await.display.name" groupBundle="messages.InspectionsBundle"
                      groupKey="group.names.threading.issues" enabledByDefault="false" level="WARNING"
@@ -2640,6 +2643,10 @@
                      bundle="com.siyeh.InspectionGadgetsBundle" key="parameter.hides.member.variable.display.name"
                      groupBundle="messages.InspectionsBundle" groupKey="group.names.visibility.issues" enabledByDefault="false"
                      level="WARNING" implementationClass="com.siyeh.ig.visibility.ParameterHidingMemberVariableInspection"/>
+    <localInspection language="JAVA" suppressId="LambdaParameterHidesMemberVariable" shortName="LambdaParameterHidingMemberVariable"
+                     bundle="com.siyeh.InspectionGadgetsBundle" key="lambda.parameter.hides.member.variable.display.name"
+                     groupBundle="messages.InspectionsBundle" groupKey="group.names.visibility.issues" enabledByDefault="false"
+                     level="WARNING" implementationClass="com.siyeh.ig.visibility.LambdaParameterHidingMemberVariableInspection"/>
   </extensions>
 
   <application-components>
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
index 7f61b37..013cf23 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
@@ -1157,7 +1157,7 @@
 local.variable.naming.convention.problem.descriptor.regex.mismatch=Local variable name <code>#ref</code> doesn''t match regex ''{0}'' #loc
 local.variable.naming.convention.ignore.option=Ignore for-loop parameters
 local.variable.naming.convention.ignore.catch.option=Ignore 'catch' block parameters
-method.names.differ.only.by.case.problem.descriptor=Method names <code>#ref</code> and ''{0}'' differ only by case #loc
+method.names.differ.only.by.case.problem.descriptor=Method name <code>#ref</code> and method name ''{0}'' differ only by case #loc
 parameter.name.differs.from.overridden.parameter.ignore.character.option=Ignore if overridden parameter contains only one character
 parameter.name.differs.from.overridden.parameter.ignore.library.option=Ignore if overridden parameter is from a library
 parameter.name.differs.from.overridden.parameter.problem.descriptor=Parameter name <code>#ref</code> is different from parameter ''{0}'' overridden #loc
@@ -2066,3 +2066,8 @@
 interface.may.be.annotated.functional.display.name=Interface may be annotated @FunctionalInterface
 interface.may.be.annotated.functional.problem.descriptor=Interface <code>#ref</code> may be annotated with @FunctionalInterface
 only.report.public.methods.option=Only report 'public' methods
+lambda.parameter.hides.member.variable.display.name=Lambda parameter hides field
+lambda.parameter.hides.member.variable.problem.descriptor=Lambda parameter <code>#ref</code> hides field in class ''{0}'' #loc
+shared.thread.local.random.display.name='ThreadLocalRandom' instance might be shared
+shared.thread.local.random.problem.descriptor='ThreadLocalRandom' instance might be shared between threads
+
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java
index 9ef4c14..31a7987 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2011 Bas Leijdekkers
+ * Copyright 2008-2014 Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
 import com.intellij.psi.search.SearchScope;
 import com.intellij.psi.search.searches.ReferencesSearch;
 import com.intellij.psi.tree.IElementType;
-import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.Query;
 import com.siyeh.InspectionGadgetsBundle;
 import com.siyeh.ig.InspectionGadgetsFix;
@@ -46,8 +45,7 @@
   }
 
   @Override
-  public void doFix(Project project, ProblemDescriptor descriptor)
-    throws IncorrectOperationException {
+  public void doFix(Project project, ProblemDescriptor descriptor) {
     final PsiReferenceExpression parameterReference =
       (PsiReferenceExpression)descriptor.getPsiElement();
     final PsiElement target = parameterReference.resolve();
@@ -79,6 +77,10 @@
         body = forBody;
       }
     }
+    else if (declarationScope instanceof PsiLambdaExpression) {
+      final PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)declarationScope;
+      body = lambdaExpression.getBody();
+    }
     else {
       return;
     }
@@ -125,15 +127,16 @@
         replaceVariableName(child, firstReference,
                             variableName, parameterName, buffer);
     }
+    if (body instanceof PsiExpression) { // expression lambda
+      buffer.insert(0, "return ");
+      buffer.append(';');
+    }
     final String replacementText;
     if (newDeclarationCreated) {
       replacementText = "{" + buffer + '}';
     }
     else {
-      final PsiType type = parameterReference.getType();
-      if (type == null) {
-        return;
-      }
+      final PsiType type = parameter.getType();
       final String className = type.getCanonicalText();
       replacementText = '{' + className + ' ' + variableName + " = " +
                         parameterName + ';' + buffer + '}';
@@ -141,8 +144,7 @@
     final PsiElementFactory elementFactory =
       JavaPsiFacade.getInstance(project).getElementFactory();
     final PsiCodeBlock block =
-      elementFactory.createCodeBlockFromText(
-        replacementText, null);
+      elementFactory.createCodeBlockFromText(replacementText, declarationScope);
     body.replace(block);
     codeStyleManager.reformat(declarationScope);
   }
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java
index 278c07e..3741d26 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ControlFlowUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
     }
     else if (statement instanceof PsiExpressionListStatement || statement instanceof PsiEmptyStatement ||
              statement instanceof PsiAssertStatement || statement instanceof PsiDeclarationStatement ||
-             statement instanceof PsiSwitchLabelStatement) {
+             statement instanceof PsiSwitchLabelStatement || statement instanceof PsiForeachStatement) {
       return true;
     }
     else if (statement instanceof PsiExpressionStatement) {
@@ -63,9 +63,6 @@
     else if (statement instanceof PsiForStatement) {
       return forStatementMayCompleteNormally((PsiForStatement)statement);
     }
-    else if (statement instanceof PsiForeachStatement) {
-      return foreachStatementMayCompleteNormally((PsiForeachStatement)statement);
-    }
     else if (statement instanceof PsiWhileStatement) {
       return whileStatementMayCompleteNormally((PsiWhileStatement)statement);
     }
@@ -130,10 +127,6 @@
     return Boolean.TRUE != value;
   }
 
-  private static boolean foreachStatementMayCompleteNormally(@NotNull PsiForeachStatement loopStatement) {
-    return true;
-  }
-
   private static boolean switchStatementMayCompleteNormally(@NotNull PsiSwitchStatement switchStatement) {
     if (statementIsBreakTarget(switchStatement)) {
       return true;
@@ -524,7 +517,7 @@
     }
   }
 
-  private static class SystemExitFinder extends JavaRecursiveElementVisitor {
+  private static class SystemExitFinder extends JavaRecursiveElementWalkingVisitor {
 
     private boolean m_found = false;
 
@@ -564,7 +557,7 @@
     }
   }
 
-  private static class ReturnFinder extends JavaRecursiveElementVisitor {
+  private static class ReturnFinder extends JavaRecursiveElementWalkingVisitor {
 
     private boolean m_found = false;
 
@@ -587,7 +580,7 @@
     }
   }
 
-  private static class BreakFinder extends JavaRecursiveElementVisitor {
+  private static class BreakFinder extends JavaRecursiveElementWalkingVisitor {
 
     private boolean m_found = false;
     private final PsiStatement m_target;
@@ -637,7 +630,7 @@
     }
   }
 
-  private static class ContinueFinder extends JavaRecursiveElementVisitor {
+  private static class ContinueFinder extends JavaRecursiveElementWalkingVisitor {
 
     private boolean m_found = false;
     private final PsiStatement m_target;
@@ -687,7 +680,7 @@
     }
   }
 
-  private static class MethodCallFinder extends JavaRecursiveElementVisitor {
+  private static class MethodCallFinder extends JavaRecursiveElementWalkingVisitor {
 
     private final String containingClassName;
     private final PsiType returnType;
@@ -728,7 +721,7 @@
     }
   }
 
-  private static class ContinueToAncestorFinder extends JavaRecursiveElementVisitor {
+  private static class ContinueToAncestorFinder extends JavaRecursiveElementWalkingVisitor {
 
     private final PsiStatement statement;
     private boolean found = false;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java
index c14da9f..ad5ecc2 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java
@@ -153,86 +153,59 @@
     }
 
     @Override
-    public void visitBinaryExpression(@NotNull PsiBinaryExpression binaryExpression) {
-      final PsiExpression rhs = binaryExpression.getROperand();
-      if (rhs == null) {
-        expectedType = null;
-        return;
+    public void visitPolyadicExpression(@NotNull PsiPolyadicExpression polyadicExpression) {
+      final PsiExpression[] operands = polyadicExpression.getOperands();
+      for (PsiExpression operand : operands) {
+        if (operand == null || operand.getType() == null) {
+          expectedType = null;
+          return;
+        }
       }
-      final PsiExpression lhs = binaryExpression.getLOperand();
-      PsiType lhsType = lhs.getType();
-      if (lhsType == null) {
-        expectedType = null;
-        return;
-      }
-      PsiType rhsType = rhs.getType();
-      if (rhsType == null) {
-        expectedType = null;
-        return;
-      }
-      final IElementType tokenType = binaryExpression.getOperationTokenType();
-      final PsiType type = binaryExpression.getType();
+      final IElementType tokenType = polyadicExpression.getOperationTokenType();
+      final PsiType type = polyadicExpression.getType();
+      final PsiType wrappedExpressionType = wrappedExpression.getType();
       if (TypeUtils.isJavaLangString(type) || isArithmeticOperation(tokenType) || isBooleanOperation(tokenType)) {
         expectedType = type;
       }
       else if (isShiftOperation(tokenType)) {
-        if (lhs == wrappedExpression) {
-          expectedType = unaryNumericPromotion(lhsType);
-        }
-        else {
-          expectedType = unaryNumericPromotion(rhsType);
-        }
+        expectedType = unaryNumericPromotion(wrappedExpressionType);
       }
-      else if (ComparisonUtils.isEqualityComparison(binaryExpression)) {
+      else if (ComparisonUtils.isEqualityComparison(polyadicExpression)) {
         // JLS 15.21.1 Numerical Equality Operators == and !=
-        final PsiType wrappedExpressionType = wrappedExpression.getType();
         if (TypeConversionUtil.isPrimitiveAndNotNull(wrappedExpressionType)) {
           expectedType = wrappedExpressionType;
-          return;
         }
-        if (lhs == wrappedExpression) {
-          if (TypeConversionUtil.isPrimitiveAndNotNull(rhsType)) {
+        else if (operands.length > 2) {
+          expectedType = PsiPrimitiveType.getUnboxedType(wrappedExpressionType);
+        }
+        else if (operands[0] == wrappedExpression) {
+          if (TypeConversionUtil.isPrimitiveAndNotNull(operands[1].getType())) {
             expectedType = PsiPrimitiveType.getUnboxedType(wrappedExpressionType);
-            return;
           }
-          expectedType = TypeUtils.getObjectType(wrappedExpression);
+          else {
+            expectedType = TypeUtils.getObjectType(wrappedExpression);
+          }
         }
         else {
-         if (TypeConversionUtil.isPrimitiveAndNotNull(lhsType)) {
+         if (TypeConversionUtil.isPrimitiveAndNotNull(operands[0].getType())) {
             expectedType = PsiPrimitiveType.getUnboxedType(wrappedExpressionType);
-            return;
-          }
-          expectedType = TypeUtils.getObjectType(wrappedExpression);
+         }
+          else {
+           expectedType = TypeUtils.getObjectType(wrappedExpression);
+         }
         }
       }
       else if (ComparisonUtils.isComparisonOperation(tokenType)) {
-        if (lhs == wrappedExpression && !TypeConversionUtil.isPrimitiveAndNotNull(lhsType)) {
-          lhsType = PsiPrimitiveType.getUnboxedType(lhsType);
-          if (lhsType == null) {
-            expectedType = null;
+        if (operands.length != 2) {
+          expectedType = null;
+          return;
+        }
+        else if (!TypeConversionUtil.isPrimitiveAndNotNull(wrappedExpressionType)) {
+          if (PsiPrimitiveType.getUnboxedType(wrappedExpressionType) == null) {
             return;
           }
         }
-        if (rhs == wrappedExpression && !TypeConversionUtil.isPrimitiveAndNotNull(rhsType)) {
-          rhsType = PsiPrimitiveType.getUnboxedType(rhsType);
-          if (rhsType == null) {
-            expectedType = null;
-            return;
-          }
-        }
-        // JLS 5.6.2 Binary Numeric Promotion
-        if (PsiType.DOUBLE.equals(lhsType) || PsiType.DOUBLE.equals(rhsType)) {
-          expectedType = PsiType.DOUBLE;
-        }
-        else if (PsiType.FLOAT.equals(lhsType) || PsiType.FLOAT.equals(rhsType)) {
-          expectedType = PsiType.FLOAT;
-        }
-        else if (PsiType.LONG.equals(lhsType) || PsiType.LONG.equals(rhsType)) {
-          expectedType = PsiType.LONG;
-        }
-        else {
-          expectedType = PsiType.INT;
-        }
+        expectedType = TypeConversionUtil.binaryNumericPromotion(operands[0].getType(), operands[1].getType());
       }
       else {
         expectedType = null;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
index 6301e83..8d52a86 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,8 +19,8 @@
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.JavaCodeStyleSettingsFacade;
 import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.InheritanceUtil;
 import com.intellij.psi.util.*;
+import com.intellij.psi.util.InheritanceUtil;
 import com.siyeh.HardcodedMethodConstants;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -247,20 +247,22 @@
         continue;
       }
       final PsiElement element = importReference.resolve();
-      if (element == null || !(element instanceof PsiPackage)) {
+      if (!(element instanceof PsiPackage)) {
         continue;
       }
       final PsiPackage aPackage = (PsiPackage)element;
-      if (!strict) {
-        return aPackage.containsClassNamed(shortName);
+      if (!strict && aPackage.containsClassNamed(shortName)) {
+        return true;
       }
-      final PsiClass[] classes = aPackage.findClassByShortName(shortName, file.getResolveScope());
-      for (final PsiClass aClass : classes) {
-        final String qualifiedClassName = aClass.getQualifiedName();
-        if (qualifiedClassName == null || fqName.equals(qualifiedClassName)) {
-          continue;
+      else {
+        final PsiClass[] classes = aPackage.findClassByShortName(shortName, file.getResolveScope());
+        for (final PsiClass aClass : classes) {
+          final String qualifiedClassName = aClass.getQualifiedName();
+          if (qualifiedClassName == null || fqName.equals(qualifiedClassName)) {
+            continue;
+          }
+          return containsConflictingReference(file, qualifiedClassName);
         }
-        return containsConflictingReference(file, qualifiedClassName);
       }
     }
     return hasJavaLangImportConflict(fqName, file);
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java
index af04c02..5063ef7 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SideEffectChecker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2006 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
     return visitor.mayHaveSideEffects();
   }
 
-  private static class SideEffectsVisitor extends JavaRecursiveElementVisitor {
+  private static class SideEffectsVisitor extends JavaRecursiveElementWalkingVisitor {
 
     private boolean mayHaveSideEffects = false;
 
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java
index e097d58..b8e7b7c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAccessUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,9 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Set;
 
 public class VariableAccessUtils {
@@ -446,4 +449,43 @@
     }
     return child;
   }
+
+  public static Set<PsiVariable> collectUsedVariables(PsiElement context) {
+    if (context == null) {
+      return Collections.emptySet();
+    }
+    final VariableCollectingVisitor visitor = new VariableCollectingVisitor();
+    context.accept(visitor);
+    return visitor.getUsedVariables();
+  }
+
+  public static boolean isAnyVariableAssigned(@NotNull Collection<PsiVariable> variables, @Nullable PsiElement context) {
+    if (context == null) {
+      return false;
+    }
+    final VariableAssignedVisitor visitor = new VariableAssignedVisitor(variables, true);
+    context.accept(visitor);
+    return visitor.isAssigned();
+  }
+
+  private static class VariableCollectingVisitor extends JavaRecursiveElementVisitor {
+
+    private final Set<PsiVariable> usedVariables = new HashSet();
+
+    @Override
+    public void visitReferenceExpression(
+      PsiReferenceExpression expression) {
+      super.visitReferenceExpression(expression);
+      final PsiElement target = expression.resolve();
+      if (!(target instanceof PsiVariable)) {
+        return;
+      }
+      final PsiVariable variable = (PsiVariable)target;
+      usedVariables.add(variable);
+    }
+
+    public Set<PsiVariable> getUsedVariables() {
+      return usedVariables;
+    }
+  }
 }
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAssignedVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAssignedVisitor.java
index 0a22ef3..279400f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAssignedVisitor.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariableAssignedVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,16 +20,25 @@
 import com.intellij.psi.util.TypeConversionUtil;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.Collection;
+import java.util.Collections;
+
 public class VariableAssignedVisitor extends JavaRecursiveElementWalkingVisitor {
 
-  @NotNull private final PsiVariable variable;
+  @NotNull private final Collection<PsiVariable> variables;
   private final boolean recurseIntoClasses;
   private final boolean checkUnaryExpressions;
   private boolean assigned = false;
   private PsiElement excludedElement = null;
 
+  public VariableAssignedVisitor(@NotNull Collection<PsiVariable> variables, boolean recurseIntoClasses) {
+    this.variables = variables;
+    checkUnaryExpressions = true;
+    this.recurseIntoClasses = recurseIntoClasses;
+  }
+
   public VariableAssignedVisitor(@NotNull PsiVariable variable, boolean recurseIntoClasses) {
-    this.variable = variable;
+    variables = Collections.singleton(variable);
     final PsiType type = variable.getType();
     checkUnaryExpressions = TypeConversionUtil.isNumericType(type);
     this.recurseIntoClasses = recurseIntoClasses;
@@ -58,8 +67,11 @@
     }
     super.visitAssignmentExpression(assignment);
     final PsiExpression lhs = assignment.getLExpression();
-    if (VariableAccessUtils.evaluatesToVariable(lhs, variable)) {
-      assigned = true;
+    for (PsiVariable variable : variables) {
+      if (VariableAccessUtils.evaluatesToVariable(lhs, variable)) {
+        assigned = true;
+        break;
+      }
     }
   }
 
@@ -85,8 +97,11 @@
       return;
     }
     final PsiExpression operand = prefixExpression.getOperand();
-    if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
-      assigned = true;
+    for (PsiVariable variable : variables) {
+      if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
+        assigned = true;
+        break;
+      }
     }
   }
 
@@ -104,8 +119,11 @@
       return;
     }
     final PsiExpression operand = postfixExpression.getOperand();
-    if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
-      assigned = true;
+    for (PsiVariable variable : variables) {
+      if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
+        assigned = true;
+        break;
+      }
     }
   }
 
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SharedThreadLocalRandomInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SharedThreadLocalRandomInspection.java
new file mode 100644
index 0000000..97adc03
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SharedThreadLocalRandomInspection.java
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ * 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.siyeh.ig.threading;
+
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
+import com.siyeh.ig.psiutils.VariableAccessUtils;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class SharedThreadLocalRandomInspection extends BaseInspection {
+  @Nls
+  @NotNull
+  @Override
+  public String getDisplayName() {
+    return InspectionGadgetsBundle.message("shared.thread.local.random.display.name");
+  }
+
+  @NotNull
+  @Override
+  protected String buildErrorString(Object... infos) {
+    return InspectionGadgetsBundle.message("shared.thread.local.random.problem.descriptor");
+  }
+
+  @Override
+  public BaseInspectionVisitor buildVisitor() {
+    return new SharedThreadLocalRandomVisitor();
+  }
+
+  private static class SharedThreadLocalRandomVisitor extends BaseInspectionVisitor {
+
+    @Override
+    public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+      super.visitMethodCallExpression(expression);
+      final PsiReferenceExpression methodExpression = expression.getMethodExpression();
+      @NonNls final String name = methodExpression.getReferenceName();
+      if (!"current".equals(name)) {
+        return;
+      }
+      final PsiMethod method = expression.resolveMethod();
+      if (method == null) {
+        return;
+      }
+      final PsiClass aClass = method.getContainingClass();
+      if (!InheritanceUtil.isInheritor(aClass, "java.util.concurrent.ThreadLocalRandom")) {
+        return;
+      }
+      if (isArgumentToMethodCall(expression)) {
+        registerMethodCallError(expression);
+      }
+      else {
+        final PsiVariable variable = assignedToVariable(expression);
+        if (variable instanceof PsiField) {
+          registerMethodCallError(expression);
+        }
+        else if (variable instanceof PsiLocalVariable) {
+          final PsiCodeBlock context = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
+          if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, context) ||
+              VariableAccessUtils.variableIsUsedInInnerClass(variable, context)) {
+            registerMethodCallError(expression);
+          }
+        }
+      }
+    }
+
+    private static boolean isArgumentToMethodCall(PsiExpression expression) {
+      final PsiElement parent = ParenthesesUtils.getParentSkipParentheses(expression);
+      if (!(parent instanceof PsiExpressionList)) {
+        return false;
+      }
+      final PsiElement grandParent = parent.getParent();
+      return grandParent instanceof PsiMethodCallExpression;
+    }
+
+    private static PsiVariable assignedToVariable(PsiMethodCallExpression expression) {
+      final PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class);
+      if (parent instanceof PsiVariable) {
+        return (PsiVariable)parent;
+      }
+      if (!(parent instanceof PsiAssignmentExpression)) {
+        return null;
+      }
+      final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
+      final PsiExpression rhs = assignmentExpression.getRExpression();
+      if (!PsiTreeUtil.isAncestor(rhs, expression, false)) {
+        return null;
+      }
+      final PsiExpression lhs = ParenthesesUtils.stripParentheses(assignmentExpression.getLExpression());
+      if (!(lhs instanceof PsiReferenceExpression)) {
+        return null;
+      }
+      final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs;
+      final PsiElement target = referenceExpression.resolve();
+      if (!(target instanceof PsiVariable)) {
+        return null;
+      }
+      return (PsiVariable)target;
+    }
+  }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspectionBase.java
new file mode 100644
index 0000000..5b245ec
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspectionBase.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
+ *
+ * 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.siyeh.ig.visibility;
+
+import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
+import com.intellij.psi.*;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.ClassUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class LambdaParameterHidingMemberVariableInspectionBase extends BaseInspection {
+
+  @SuppressWarnings("PublicField")
+  public boolean m_ignoreInvisibleFields = true;
+
+  @Override
+  @NotNull
+  public String getID() {
+    return "LambdaParameterHidesMemberVariable";
+  }
+
+  @Override
+  @NotNull
+  public String getDisplayName() {
+    return InspectionGadgetsBundle.message("lambda.parameter.hides.member.variable.display.name");
+  }
+
+  @Override
+  protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
+    return true;
+  }
+
+  @Override
+  @NotNull
+  public String buildErrorString(Object... infos) {
+    final PsiClass aClass = (PsiClass)infos[0];
+    return InspectionGadgetsBundle.message("lambda.parameter.hides.member.variable.problem.descriptor", aClass.getName());
+  }
+
+  @Override
+  public JComponent createOptionsPanel() {
+    final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
+    optionsPanel.addCheckbox(InspectionGadgetsBundle.message("parameter.hides.member.variable.ignore.superclass.option"),
+                             "m_ignoreInvisibleFields");
+    return optionsPanel;
+  }
+
+  @Override
+  public BaseInspectionVisitor buildVisitor() {
+    return new LambdaParameterHidingMemberVariableVisitor();
+  }
+
+  private class LambdaParameterHidingMemberVariableVisitor extends BaseInspectionVisitor {
+
+    @Override
+    public void visitParameter(@NotNull PsiParameter variable) {
+      super.visitParameter(variable);
+      final PsiElement declarationScope = variable.getDeclarationScope();
+      if (!(declarationScope instanceof PsiLambdaExpression)) {
+        return;
+      }
+      final PsiClass aClass = checkFieldName(variable);
+      if (aClass ==  null) {
+        return;
+      }
+      registerVariableError(variable, aClass);
+    }
+
+    @Nullable
+    private PsiClass checkFieldName(PsiVariable variable) {
+      final String variableName = variable.getName();
+      if (variableName == null) {
+        return null;
+      }
+      PsiClass aClass = ClassUtils.getContainingClass(variable);
+      while (aClass != null) {
+        final PsiField[] fields = aClass.getAllFields();
+        for (PsiField field : fields) {
+          final String fieldName = field.getName();
+          if (!variableName.equals(fieldName)) {
+            continue;
+          }
+          if (!m_ignoreInvisibleFields || ClassUtils.isFieldVisible(field, aClass)) {
+            return aClass;
+          }
+        }
+        aClass = ClassUtils.getContainingClass(aClass);
+      }
+      return null;
+    }
+  }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspection.java
new file mode 100644
index 0000000..4112dfe
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspection.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
+ *
+ * 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.siyeh.ig.visibility;
+
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.RenameFix;
+
+public class LambdaParameterHidingMemberVariableInspection extends LambdaParameterHidingMemberVariableInspectionBase {
+  @Override
+  protected InspectionGadgetsFix buildFix(Object... infos) {
+    return new RenameFix();
+  }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/LambdaParameterHidingMemberVariable.html b/plugins/InspectionGadgets/src/inspectionDescriptions/LambdaParameterHidingMemberVariable.html
new file mode 100644
index 0000000..3817e40
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/LambdaParameterHidingMemberVariable.html
@@ -0,0 +1,11 @@
+<html>
+<body>
+Reports lambda parameters named identically to visible fields of the surrounding classes
+and their superclasses.
+<!-- tooltip end -->
+<p>
+Use the checkbox below to ignore fields that are not actually visible from the lambda expression, for example <b>private</b> fields
+<p>
+<small>New in 13.1</small>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SharedThreadLocalRandom.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SharedThreadLocalRandom.html
new file mode 100644
index 0000000..07ebcca
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SharedThreadLocalRandom.html
@@ -0,0 +1,15 @@
+<html>
+<body>
+Reports <b>java.util.concurrent.ThreadLocalRandom</b> instances which might be shared between threads.
+A <b>ThreadLocalRandom</b> might be shared between threads and is reported when it is assigned to a field,
+used as a method argument or assigned to a local variable and used in anonymous or nested classes.
+A <b>ThreadLocalRandom</b> should not be shared between threads because that is not thread-safe.
+<p>
+Usages of <b>ThreadLocalRandom</b> should typically look like <b>ThreadLocalRandom.current().nextInt(...)</b>
+(or <b>nextDouble(...)</b> etc.).
+When all usages are in this form, <b>ThreadLocalRandom</b> instances can not be used accidentally by multiple threads.
+<!-- tooltip end -->
+<p>
+<small>New in 13.1</small>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ThreadLocalNotStaticFinal.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ThreadLocalNotStaticFinal.html
index 2cb9e55..e78d9c1 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ThreadLocalNotStaticFinal.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ThreadLocalNotStaticFinal.html
@@ -1,5 +1,6 @@
 <html>
 <body>
+Reports fields of type <b>java.lang.ThreadLocal</b> which are not declared <b>static final</b>.
 In the most common case a <b>java.lang.ThreadLocal</b> instance
 associates state with a thread. A non-static non-final
 <b>java.lang.ThreadLocal</b> field associates state with
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_unboxing/AutoUnboxing.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_unboxing/AutoUnboxing.java
index a39bd53..e598f07 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_unboxing/AutoUnboxing.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_unboxing/AutoUnboxing.java
@@ -59,4 +59,8 @@
         if ((boolean) b) {}
         if ((int)n) {}
     }
+
+    boolean polyadic() {
+        return true && Boolean.TRUE && true;
+    }
 }
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_unboxing/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_unboxing/expected.xml
index 431f5ca..a1ceb62 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_unboxing/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_unboxing/expected.xml
@@ -106,4 +106,10 @@
     <description>Auto-unboxing &lt;code&gt;n&lt;/code&gt; #loc</description>
   </problem>
 
+  <problem>
+    <file>AutoUnboxing.java</file>
+    <line>64</line>
+    <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Auto-unboxing</problem_class>
+    <description>Auto-unboxing &lt;code&gt;Boolean.TRUE&lt;/code&gt; #loc</description>
+  </problem>
 </problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/method_names_differ_only_by_case/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/method_names_differ_only_by_case/expected.xml
index 570e237..3c9a518 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/method_names_differ_only_by_case/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/method_names_differ_only_by_case/expected.xml
@@ -4,35 +4,35 @@
     <file>MethodNamesDifferOnlyByCase.java</file>
     <line>20</line>
     <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Method names differing only by case</problem_class>
-    <description>Method names &lt;code&gt;hashcode&lt;/code&gt; and 'hashCode' differ only by case #loc</description>
+    <description>Method name &lt;code&gt;hashcode&lt;/code&gt; and method name 'hashCode' differ only by case #loc</description>
   </problem>
 
   <problem>
     <file>MethodNamesDifferOnlyByCase.java</file>
     <line>30</line>
     <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Method names differing only by case</problem_class>
-    <description>Method names &lt;code&gt;xX&lt;/code&gt; and 'xx' differ only by case #loc</description>
+    <description>Method name &lt;code&gt;xX&lt;/code&gt; and method name 'xx' differ only by case #loc</description>
   </problem>
 
   <problem>
     <file>MethodNamesDifferOnlyByCase.java</file>
     <line>5</line>
     <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Method names differing only by case</problem_class>
-    <description>Method names &lt;code&gt;fooBar&lt;/code&gt; and 'fooBAr' differ only by case #loc</description>
+    <description>Method name &lt;code&gt;fooBar&lt;/code&gt; and method name 'fooBAr' differ only by case #loc</description>
   </problem>
 
   <problem>
     <file>MethodNamesDifferOnlyByCase.java</file>
     <line>10</line>
     <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Method names differing only by case</problem_class>
-    <description>Method names &lt;code&gt;fooBAr&lt;/code&gt; and 'fooBar' differ only by case #loc</description>
+    <description>Method name &lt;code&gt;fooBAr&lt;/code&gt; and method name 'fooBar' differ only by case #loc</description>
   </problem>
 
   <problem>
     <file>MethodNamesDifferOnlyByCase.java</file>
     <line>29</line>
     <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Method names differing only by case</problem_class>
-    <description>Method names &lt;code&gt;xx&lt;/code&gt; and 'xX' differ only by case #loc</description>
+    <description>Method name &lt;code&gt;xx&lt;/code&gt; and method name 'xX' differ only by case #loc</description>
   </problem>
 
 </problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/IGQuickFixesTestCase.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/IGQuickFixesTestCase.java
index b56c340..2ce63ec 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/IGQuickFixesTestCase.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/IGQuickFixesTestCase.java
@@ -21,6 +21,7 @@
 import com.intellij.pom.java.LanguageLevel;
 import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
 import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
+import com.intellij.util.ArrayUtil;
 import org.intellij.lang.annotations.Language;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -38,19 +39,33 @@
   protected void setUp() throws Exception {
     super.setUp();
 
-    final BaseInspection inspection = getInspection();
-    if (inspection != null) {
-      myFixture.enableInspections(inspection);
+    for (String environmentClass : getEnvironmentClasses()) {
+      myFixture.addClass(environmentClass);
     }
+    myFixture.enableInspections(getInspections());
   }
 
   protected BaseInspection getInspection() {
     return null;
   }
 
+  protected BaseInspection[] getInspections() {
+    final BaseInspection inspection = getInspection();
+    if (inspection != null) {
+      return new BaseInspection[] {inspection};
+    }
+    return new BaseInspection[0];
+  }
+
+  @NonNls
+  @Language("JAVA")
+  protected String[] getEnvironmentClasses() {
+    return ArrayUtil.EMPTY_STRING_ARRAY;
+  }
+
   @Override
   protected void tuneFixture(final JavaModuleFixtureBuilder builder) throws Exception {
-    builder.setLanguageLevel(LanguageLevel.JDK_1_7);
+    builder.setLanguageLevel(LanguageLevel.JDK_1_8);
   }
 
   @Override
@@ -79,16 +94,16 @@
 
   protected void doExpressionTest(
     String hint,
-    @Language(value = "JAVA", prefix = "class X {{System.out.print(", suffix = ");}}") @NotNull @NonNls String before,
-    @Language(value = "JAVA", prefix = "class X {{System.out.print(", suffix = ");}}") @NotNull @NonNls String after) {
-    doTest(hint, "class X {{System.out.print(" + before + ");}}", "class X {{System.out.print(" + after + ");}}");
+    @Language(value = "JAVA", prefix = "class $X$ {{System.out.print(", suffix = ");}}") @NotNull @NonNls String before,
+    @Language(value = "JAVA", prefix = "class $X$ {{System.out.print(", suffix = ");}}") @NotNull @NonNls String after) {
+    doTest(hint, "class $X$ {{System.out.print(" + before + ");}}", "class $X$ {{System.out.print(" + after + ");}}");
   }
 
   protected void doMemberTest(
     String hint,
-    @Language(value = "JAVA", prefix = "class X {", suffix = "}") @NotNull @NonNls String before,
-    @Language(value = "JAVA", prefix = "class X {", suffix = "}") @NotNull @NonNls String after) {
-    doTest(hint, "class X {" + before + "}", "class X {" + after + "}");
+    @Language(value = "JAVA", prefix = "class $X$ {", suffix = "}") @NotNull @NonNls String before,
+    @Language(value = "JAVA", prefix = "class $X$ {", suffix = "}") @NotNull @NonNls String after) {
+    doTest(hint, "class $X$ {" + before + "}", "class $X$ {\n    " + after + "\n}");
   }
 
   protected void doTest(String hint, @Language("JAVA") @NotNull @NonNls String before, @Language("JAVA") @NotNull @NonNls String after) {
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFixTest.java
new file mode 100644
index 0000000..b8b74ae
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFixTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ * 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.siyeh.ig.fixes;
+
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.IGQuickFixesTestCase;
+import com.siyeh.ig.assignment.AssignmentToCatchBlockParameterInspection;
+import com.siyeh.ig.assignment.AssignmentToForLoopParameterInspection;
+import com.siyeh.ig.assignment.AssignmentToMethodParameterInspection;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ExtractParameterAsLocalVariableFixTest extends IGQuickFixesTestCase {
+
+
+  @Override
+  protected BaseInspection[] getInspections() {
+    final AssignmentToForLoopParameterInspection inspection2 = new AssignmentToForLoopParameterInspection();
+    inspection2.m_checkForeachParameters = true;
+    return new BaseInspection[] {
+      new AssignmentToMethodParameterInspection(),
+      inspection2,
+      new AssignmentToCatchBlockParameterInspection()
+    };
+  }
+
+  @Override
+  protected String[] getEnvironmentClasses() {
+    return new String[] {"class A {}",
+      "public interface Function<T, R> {\n" +
+      "    R apply(T t);" +
+      "}"};
+  }
+
+  public void testLambdaWithExpressionBody() {
+    doTest(
+      InspectionGadgetsBundle.message("extract.parameter.as.local.variable.quickfix"),
+      "class X {" +
+      "  Function<A, A> f = (a) -> a/**/ = null;" +
+      "}",
+      "class X {" +
+      "  Function<A, A> f = (a) -> {\n" +
+      "    A a1 = a;\n" +
+      "    return a1 = null;\n" +
+      "};}"
+    );
+  }
+
+  public void testSimpleMethod() {
+    doTest(
+      InspectionGadgetsBundle.message("extract.parameter.as.local.variable.quickfix"),
+      "class X {" +
+      "  void m(String s) {" +
+      "    /**/s = \"hello\";" +
+      "    System.out.println(s);" +
+      "  }" +
+      "}",
+      "class X {\n" +
+      "    void m(String s) {\n" +
+      "        String s1 = \"hello\";\n" +
+      "        System.out.println(s1);\n" +
+      "    }\n" +
+      "}"
+    );
+  }
+
+  public void testSimpleForeach() {
+    doTest(
+      InspectionGadgetsBundle.message("extract.parameter.as.local.variable.quickfix"),
+      "class X {" +
+      "  void m() {" +
+      "    for (String s : new String[]{\"one\", \"two\", \"three\"})" +
+      "      s/**/ = \"four\";" +
+      "}}",
+      "class X {" +
+      "  void m() {\n" +
+      "    for (String s : new String[]{\"one\", \"two\", \"three\"}){\n" +
+      "        String s1 = \"four\";\n" +
+      "    }\n" +
+      "}}"
+    );
+  }
+
+  public void testSimleCatchBlock() {
+    doTest(
+      InspectionGadgetsBundle.message("extract.parameter.as.local.variable.quickfix"),
+      "class X {" +
+      "  void m() {" +
+      "    try (java.io.InputStream in = null) {" +
+      "    } catch (java.io.IOException e) {" +
+      "      e/**/ = null;" +
+      "      System.out.println(e);" +
+      "    }" +
+      "  }" +
+      "}",
+      "class X {" +
+      "  void m() {" +
+      "    try (java.io.InputStream in = null) {" +
+      "    } catch (java.io.IOException e) {\n" +
+      "    java.io.IOException e1 = null;\n" +
+      "    System.out.println(e1);\n" +
+      "}\n" +
+      "}}"
+    );
+  }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/imports/UnusedImportInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/imports/UnusedImportInspectionTest.java
index 9f19674..d9dda5a 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/imports/UnusedImportInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/imports/UnusedImportInspectionTest.java
@@ -87,6 +87,21 @@
            "}");
   }
 
+  public void testNoWarn() {
+    addEnvironmentClass("package java.awt; public class List extends Component {}");
+    doTest("import javax.swing.*;\n" +
+           "import java.awt.*;\n" +
+           "import java.util.*;\n" +
+           "import java.util.List;\n" +
+           "\n" +
+           "class ImportTest extends Component {\n" +
+           "\n" +
+           "  Collection<String> c;\n" +
+           "  List<Integer> l;\n" +
+           "  JComponent jc;\n" +
+           "}");
+  }
+
   @Override
   protected LocalInspectionTool getInspection() {
     return new UnusedImportInspection();
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/SharedThreadLocalRandomInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/SharedThreadLocalRandomInspectionTest.java
new file mode 100644
index 0000000..b15bc35
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/SharedThreadLocalRandomInspectionTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ * 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.siyeh.ig.threading;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class SharedThreadLocalRandomInspectionTest extends LightInspectionTestCase {
+  @Override
+  protected InspectionProfileEntry getInspection() {
+    return new SharedThreadLocalRandomInspection();
+  }
+
+  @Override
+  protected String[] getEnvironmentClasses() {
+    return new String[] {
+      "package java.util.concurrent;\n" +
+      "import java.util.Random;" +
+      "public class ThreadLocalRandom extends Random {" +
+      "  public static ThreadLocalRandom current() {" +
+      "    return null;" +
+      "  }" +
+      "}"
+    };
+  }
+
+  public void testNoWarn() {
+    doStatementTest("System.out.println(java.util.concurrent.ThreadLocalRandom.current().nextInt());");
+  }
+
+  public void testArgument() {
+    doStatementTest("System.out.println(java.util.concurrent.ThreadLocalRandom./*'ThreadLocalRandom' instance might be shared between threads*/current/**/());");
+  }
+
+  public void testNoWarn2() {
+    doMemberTest("void m() {" +
+                 "  java.util.concurrent.ThreadLocalRandom r = java.util.concurrent.ThreadLocalRandom.current();" +
+                 "}");
+  }
+
+  public void testNestedClass() {
+    doMemberTest("void m() {" +
+                 "  java.util.concurrent.ThreadLocalRandom r = java.util.concurrent.ThreadLocalRandom./*'ThreadLocalRandom' instance might be shared between threads*/current/**/();" +
+                 "  class Z extends Thread {" +
+                 "    public void run() {" +
+                 "      System.out.println(r.nextInt(1));" +
+                 "    }" +
+                 "  }" +
+                 "}");
+  }
+
+  public void testAssignmentToField() {
+    doTest("import java.util.concurrent.ThreadLocalRandom;" +
+           "class A {" +
+           "  private ThreadLocalRandom r;" +
+           "  void m() {" +
+           "    r = ThreadLocalRandom./*'ThreadLocalRandom' instance might be shared between threads*/current/**/();" +
+           "  }" +
+           "}");
+  }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspectionTest.java
new file mode 100644
index 0000000..e7c3b75
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/visibility/LambdaParameterHidingMemberVariableInspectionTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ * 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.siyeh.ig.visibility;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class LambdaParameterHidingMemberVariableInspectionTest extends LightInspectionTestCase {
+  @Override
+  protected InspectionProfileEntry getInspection() {
+    return new LambdaParameterHidingMemberVariableInspection();
+  }
+
+  @Override
+  protected String[] getEnvironmentClasses() {
+    return new String[] {"package java.util.function;" +
+                         "public interface Function<T, R> {" +
+                         "    R apply(T t);" +
+                         "}"};
+  }
+
+  public void testSimple() {
+    doTest("import java.util.function.Function;" +
+           "class X {" +
+           "  private String s;" +
+           "" +
+           "  void m() {" +
+           "    Function<String, String> f = (/*Lambda parameter 's' hides field in class 'X'*/s/**/) -> null;" +
+           "  }" +
+           "}");
+  }
+}
diff --git a/plugins/IntelliLang/src/META-INF/plugin.xml b/plugins/IntelliLang/src/META-INF/plugin.xml
index 3473135..b62e139 100644
--- a/plugins/IntelliLang/src/META-INF/plugin.xml
+++ b/plugins/IntelliLang/src/META-INF/plugin.xml
@@ -2,7 +2,19 @@
   <name>IntelliLang</name>
   <id>org.intellij.intelliLang</id>
   <vendor>JetBrains</vendor>
-  <description><![CDATA[User configurable language injection support (originally developed by Sascha Weinreuter sascha.weinreuter@cit.de)]]></description>
+  <description>
+      <![CDATA[
+      Enables user configurable language injection support (originally developed by Sascha Weinreuter sascha.weinreuter@cit.de)
+        The following features are available:
+        <ul>
+        <li>Language injection</li>
+        <li>Pattern validation</li>
+        <li>Regular expression support</li>
+        <li>Language Injections page in the Settings/Preferences dialog.</li>
+        <li>Ability to edit injected code in the special scratch-pad editor.</l>
+        </ul>
+      ]]>
+   </description>
   <version>8.0</version>
 
   <depends optional="true" config-file="intellilang-xpath-support.xml">XPathView</depends>
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/BaseBracesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/BaseBracesIntention.java
index 9b1e57a..ecaa8ac 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/BaseBracesIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/BaseBracesIntention.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
  */
 package com.siyeh.ipp.braces;
 
-import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.*;
 import com.siyeh.IntentionPowerPackBundle;
 import com.siyeh.ipp.base.MutablyNamedIntention;
@@ -57,59 +56,21 @@
     final PsiElement parent = element.getParent();
     if (parent instanceof PsiIfStatement) {
       final PsiIfStatement ifStatement = (PsiIfStatement)parent;
-      if (isBetweenThen(ifStatement, element)) {
-        return ifStatement.getThenBranch();
-      }
-
-      if (isBetweenElse(ifStatement, element)) {
+      final PsiStatement thenBranch = ifStatement.getThenBranch();
+      final int offset = element.getTextOffset();
+      if (thenBranch != null && offset > thenBranch.getTextOffset()) {
+        final PsiKeyword elseElement = ifStatement.getElseElement();
+        if (elseElement == null || offset < elseElement.getTextOffset()) {
+          // no 'else' branch or after 'then' branch but before 'else' keyword
+          return null;
+        }
         return ifStatement.getElseBranch();
       }
+      return thenBranch;
     }
-    if (parent instanceof PsiWhileStatement) {
-      return ((PsiWhileStatement)parent).getBody();
-    }
-    if (parent instanceof PsiDoWhileStatement) {
-      return ((PsiDoWhileStatement)parent).getBody();
-    }
-    if (parent instanceof PsiForStatement) {
-      return ((PsiForStatement)parent).getBody();
-    }
-    if (parent instanceof PsiForeachStatement) {
-      return ((PsiForeachStatement)parent).getBody();
+    if (parent instanceof PsiLoopStatement) {
+      return ((PsiLoopStatement)parent).getBody();
     }
     return null;
   }
-
-  private static boolean isBetweenThen(@NotNull PsiIfStatement ifStatement, @NotNull PsiElement element) {
-    final PsiElement rParenth = ifStatement.getRParenth();
-    final PsiElement elseElement = ifStatement.getElseElement();
-
-    if (rParenth == null) {
-      return false;
-    }
-
-    if (elseElement == null) {
-      return true;
-    }
-
-    final TextRange rParenthTextRangeTextRange = rParenth.getTextRange();
-    final TextRange elseElementTextRange = elseElement.getTextRange();
-    final TextRange elementTextRange = element.getTextRange();
-
-    return new TextRange(rParenthTextRangeTextRange.getEndOffset(), elseElementTextRange.getStartOffset()).contains(elementTextRange);
-  }
-
-  private static boolean isBetweenElse(@NotNull PsiIfStatement ifStatement, @NotNull PsiElement element) {
-    final PsiElement elseElement = ifStatement.getElseElement();
-
-    if (elseElement == null) {
-      return false;
-    }
-
-    final TextRange ifStatementTextRange = ifStatement.getTextRange();
-    final TextRange elseElementTextRange = elseElement.getTextRange();
-    final TextRange elementTextRange = element.getTextRange();
-
-    return new TextRange(elseElementTextRange.getStartOffset(), ifStatementTextRange.getEndOffset()).contains(elementTextRange);
-  }
 }
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitMultiCatchIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitMultiCatchIntention.java
index f028807..c58edc1 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitMultiCatchIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitMultiCatchIntention.java
@@ -17,12 +17,15 @@
 
 import com.intellij.psi.*;
 import com.intellij.psi.impl.PsiImplUtil;
+import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.IncorrectOperationException;
 import com.siyeh.ipp.base.Intention;
 import com.siyeh.ipp.base.PsiElementPredicate;
 import org.jetbrains.annotations.NotNull;
 
-import static com.intellij.psi.PsiAnnotation.TargetType;
+import java.util.List;
+
+import static com.intellij.util.ObjectUtils.assertNotNull;
 
 public class SplitMultiCatchIntention extends Intention {
 
@@ -52,27 +55,30 @@
       return;
     }
 
-    final PsiModifierList modifierList = parameter.getModifierList();
-    if (modifierList != null) {
-      for (PsiAnnotation annotation : modifierList.getAnnotations()) {
-        if (PsiImplUtil.findApplicableTarget(annotation, TargetType.TYPE_USE) == TargetType.TYPE_USE) {
-          annotation.delete();
+    final PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject());
+    final List<PsiTypeElement> disjunctions = PsiTreeUtil.getChildrenOfTypeAsList(parameter.getTypeElement(), PsiTypeElement.class);
+    for (int i = 0; i < disjunctions.size(); i++) {
+      final PsiCatchSection copy = (PsiCatchSection)catchSection.copy();
+
+      final PsiTypeElement typeElement = assertNotNull(assertNotNull(copy.getParameter()).getTypeElement());
+      final PsiTypeElement newTypeElement = factory.createTypeElementFromText(disjunctions.get(i).getText(), catchSection);
+      typeElement.replace(newTypeElement);
+
+      grandParent.addBefore(copy, catchSection);
+
+      if (i == 0) {
+        // clear the original from type annotations: they belong to the first disjunction and should not appear in others
+        final PsiModifierList modifierList = parameter.getModifierList();
+        if (modifierList != null) {
+          for (PsiAnnotation annotation : modifierList.getAnnotations()) {
+            if (PsiImplUtil.findApplicableTarget(annotation, PsiAnnotation.TargetType.TYPE_USE) == PsiAnnotation.TargetType.TYPE_USE) {
+              annotation.delete();
+            }
+          }
         }
       }
     }
 
-    final PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject());
-    for (PsiType disjunction : ((PsiDisjunctionType)type).getDisjunctions()) {
-      final PsiCatchSection copy = (PsiCatchSection)catchSection.copy();
-      final PsiParameter copyParameter = copy.getParameter();
-      assert copyParameter != null : copy.getText();
-      final PsiTypeElement typeElement = copyParameter.getTypeElement();
-      assert typeElement != null : copyParameter.getText();
-      final PsiTypeElement newTypeElement = factory.createTypeElement(disjunction);
-      typeElement.replace(newTypeElement);
-      grandParent.addBefore(copy, catchSection);
-    }
-
     catchSection.delete();
   }
 }
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionIntention.java
index 35404ae..d76eaaf 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionIntention.java
@@ -22,9 +22,9 @@
 import com.siyeh.ig.psiutils.ComparisonUtils;
 import com.siyeh.ig.psiutils.ExpressionUtils;
 import com.siyeh.ig.psiutils.ParenthesesUtils;
+import com.siyeh.ig.psiutils.VariableAccessUtils;
 import com.siyeh.ipp.base.Intention;
 import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.VariableAccessUtils;
 import org.jetbrains.annotations.NotNull;
 
 public class ReverseForLoopDirectionIntention extends Intention {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionPredicate.java
index f37d900..ef8b6d7 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionPredicate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009-2013 Bas Leijdekkers
+ * Copyright 2009-2014 Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,10 +15,14 @@
  */
 package com.siyeh.ipp.forloop;
 
+import com.siyeh.ig.psiutils.ComparisonUtils;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
+import com.siyeh.ig.psiutils.VariableAccessUtils;
 import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.VariableAccessUtils;
 import com.intellij.psi.*;
 import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 class ReverseForLoopDirectionPredicate implements PsiElementPredicate {
 
@@ -57,11 +61,109 @@
       return false;
     }
     final PsiExpression condition = forStatement.getCondition();
-    if (!VariableAccessUtils.isVariableCompared(variable, condition)) {
+    if (!isVariableCompared(variable, condition)) {
       return false;
     }
     final PsiStatement update = forStatement.getUpdate();
-    return VariableAccessUtils.isVariableIncrementOrDecremented(variable,
-                                                                update);
+    return isVariableIncrementOrDecremented(variable, update);
+  }
+
+  public static boolean isVariableCompared(
+    @NotNull PsiVariable variable, @Nullable PsiExpression expression) {
+    if (!(expression instanceof PsiBinaryExpression)) {
+      return false;
+    }
+    final PsiBinaryExpression binaryExpression =
+      (PsiBinaryExpression)expression;
+    final IElementType tokenType = binaryExpression.getOperationTokenType();
+    if (!ComparisonUtils.isComparisonOperation(tokenType)) {
+      return false;
+    }
+    final PsiExpression lhs = binaryExpression.getLOperand();
+    final PsiExpression rhs = binaryExpression.getROperand();
+    if (rhs == null) {
+      return false;
+    }
+    if (VariableAccessUtils.evaluatesToVariable(lhs, variable)) {
+      return true;
+    }
+    else if (VariableAccessUtils.evaluatesToVariable(rhs, variable)) {
+      return true;
+    }
+    return false;
+  }
+
+  public static boolean isVariableIncrementOrDecremented(
+    @NotNull PsiVariable variable, @Nullable PsiStatement statement) {
+    if (!(statement instanceof PsiExpressionStatement)) {
+      return false;
+    }
+    final PsiExpressionStatement expressionStatement =
+      (PsiExpressionStatement)statement;
+    PsiExpression expression = expressionStatement.getExpression();
+    expression = ParenthesesUtils.stripParentheses(expression);
+    if (expression instanceof PsiPrefixExpression) {
+      final PsiPrefixExpression prefixExpression =
+        (PsiPrefixExpression)expression;
+      final IElementType tokenType = prefixExpression.getOperationTokenType();
+      if (!tokenType.equals(JavaTokenType.PLUSPLUS) &&
+          !tokenType.equals(JavaTokenType.MINUSMINUS)) {
+        return false;
+      }
+      final PsiExpression operand = prefixExpression.getOperand();
+      return VariableAccessUtils.evaluatesToVariable(operand, variable);
+    }
+    else if (expression instanceof PsiPostfixExpression) {
+      final PsiPostfixExpression postfixExpression =
+        (PsiPostfixExpression)expression;
+      final IElementType tokenType = postfixExpression.getOperationTokenType();
+      if (!tokenType.equals(JavaTokenType.PLUSPLUS) &&
+          !tokenType.equals(JavaTokenType.MINUSMINUS)) {
+        return false;
+      }
+      final PsiExpression operand = postfixExpression.getOperand();
+      return VariableAccessUtils.evaluatesToVariable(operand, variable);
+    }
+    else if (expression instanceof PsiAssignmentExpression) {
+      final PsiAssignmentExpression assignmentExpression =
+        (PsiAssignmentExpression)expression;
+      final IElementType tokenType =
+        assignmentExpression.getOperationTokenType();
+      PsiExpression lhs = assignmentExpression.getLExpression();
+      lhs = ParenthesesUtils.stripParentheses(lhs);
+      if (!VariableAccessUtils.evaluatesToVariable(lhs, variable)) {
+        return false;
+      }
+      PsiExpression rhs = assignmentExpression.getRExpression();
+      rhs = ParenthesesUtils.stripParentheses(rhs);
+      if (tokenType == JavaTokenType.EQ) {
+        if (!(rhs instanceof PsiBinaryExpression)) {
+          return false;
+        }
+        final PsiBinaryExpression binaryExpression =
+          (PsiBinaryExpression)rhs;
+        final IElementType token =
+          binaryExpression.getOperationTokenType();
+        if (!token.equals(JavaTokenType.PLUS) &&
+            !token.equals(JavaTokenType.MINUS)) {
+          return false;
+        }
+        PsiExpression lOperand = binaryExpression.getLOperand();
+        lOperand = ParenthesesUtils.stripParentheses(lOperand);
+        PsiExpression rOperand = binaryExpression.getROperand();
+        rOperand = ParenthesesUtils.stripParentheses(rOperand);
+        if (VariableAccessUtils.evaluatesToVariable(rOperand, variable)) {
+          return true;
+        }
+        else if (VariableAccessUtils.evaluatesToVariable(lOperand, variable)) {
+          return true;
+        }
+      }
+      else if (tokenType == JavaTokenType.PLUSEQ ||
+               tokenType == JavaTokenType.MINUSEQ) {
+        return true;
+      }
+    }
+    return false;
   }
 }
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceAssignmentWithPostfixExpressionPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceAssignmentWithPostfixExpressionPredicate.java
index e239e85..89cd997 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceAssignmentWithPostfixExpressionPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceAssignmentWithPostfixExpressionPredicate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009-2013 Bas Leijdekkers
+ * Copyright 2009-2014 Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,8 +18,8 @@
 import com.intellij.psi.*;
 import com.intellij.psi.tree.IElementType;
 import com.siyeh.ig.psiutils.ParenthesesUtils;
+import com.siyeh.ig.psiutils.VariableAccessUtils;
 import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.VariableAccessUtils;
 
 class ReplaceAssignmentWithPostfixExpressionPredicate implements PsiElementPredicate {
 
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceableWithOperatorAssignmentPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceableWithOperatorAssignmentPredicate.java
index 959c858..34a2d08 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceableWithOperatorAssignmentPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceableWithOperatorAssignmentPredicate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,10 +18,10 @@
 import com.intellij.psi.*;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiUtil;
-import com.siyeh.ipp.base.PsiElementPredicate;
 import com.siyeh.ig.psiutils.EquivalenceChecker;
+import com.siyeh.ig.psiutils.SideEffectChecker;
+import com.siyeh.ipp.base.PsiElementPredicate;
 import com.siyeh.ipp.psiutils.ErrorUtil;
-import com.siyeh.ipp.psiutils.SideEffectChecker;
 
 class ReplaceableWithOperatorAssignmentPredicate implements PsiElementPredicate {
 
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConditionalUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConditionalUtils.java
deleted file mode 100644
index 8d13fe2..0000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConditionalUtils.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
- *
- * 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.siyeh.ipp.psiutils;
-
-import com.intellij.psi.*;
-import org.jetbrains.annotations.NonNls;
-
-public class ConditionalUtils {
-
-  private ConditionalUtils() {}
-
-  public static boolean isReturn(PsiStatement statement,
-                                 @NonNls String value) {
-    if (statement == null) {
-      return false;
-    }
-    if (!(statement instanceof PsiReturnStatement)) {
-      return false;
-    }
-    final PsiReturnStatement returnStatement =
-      (PsiReturnStatement)statement;
-    if (returnStatement.getReturnValue() == null) {
-      return false;
-    }
-    final PsiExpression returnValue = returnStatement.getReturnValue();
-    if (returnValue == null) {
-      return false;
-    }
-    final String returnValueText = returnValue.getText();
-    return value.equals(returnValueText);
-  }
-
-  public static boolean isAssignment(PsiStatement statement,
-                                     @NonNls String value) {
-    if (statement == null) {
-      return false;
-    }
-    if (!(statement instanceof PsiExpressionStatement)) {
-      return false;
-    }
-    final PsiExpressionStatement expressionStatement =
-      (PsiExpressionStatement)statement;
-    final PsiExpression expression = expressionStatement.getExpression();
-    if (!(expression instanceof PsiAssignmentExpression)) {
-      return false;
-    }
-    final PsiAssignmentExpression assignment =
-      (PsiAssignmentExpression)expression;
-    final PsiExpression rhs = assignment.getRExpression();
-    if (rhs == null) {
-      return false;
-    }
-    final String rhsText = rhs.getText();
-    return value.equals(rhsText);
-  }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ControlFlowUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ControlFlowUtils.java
deleted file mode 100644
index 668444b..0000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ControlFlowUtils.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
- *
- * 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.siyeh.ipp.psiutils;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-
-public class ControlFlowUtils {
-
-  private ControlFlowUtils() {
-  }
-
-  public static boolean statementMayCompleteNormally(PsiStatement statement) {
-    if (statement instanceof PsiBreakStatement ||
-        statement instanceof PsiContinueStatement ||
-        statement instanceof PsiReturnStatement ||
-        statement instanceof PsiThrowStatement) {
-      return false;
-    }
-    else if (statement instanceof PsiExpressionListStatement ||
-             statement instanceof PsiExpressionStatement ||
-             statement instanceof PsiEmptyStatement ||
-             statement instanceof PsiAssertStatement ||
-             statement instanceof PsiDeclarationStatement) {
-      return true;
-    }
-    else if (statement instanceof PsiForStatement) {
-      final PsiForStatement loopStatement = (PsiForStatement)statement;
-      final PsiExpression test = loopStatement.getCondition();
-      return test != null && !isBooleanConstant(test, true) ||
-             statementIsBreakTarget(loopStatement);
-    }
-    else if (statement instanceof PsiForeachStatement) {
-      return true;
-    }
-    else if (statement instanceof PsiWhileStatement) {
-      final PsiWhileStatement loopStatement =
-        (PsiWhileStatement)statement;
-      final PsiExpression test = loopStatement.getCondition();
-      return !isBooleanConstant(test, true)
-             || statementIsBreakTarget(loopStatement);
-    }
-    else if (statement instanceof PsiDoWhileStatement) {
-      final PsiDoWhileStatement loopStatement =
-        (PsiDoWhileStatement)statement;
-      final PsiExpression test = loopStatement.getCondition();
-      final PsiStatement body = loopStatement.getBody();
-      return statementMayCompleteNormally(body) &&
-             !isBooleanConstant(test, true)
-             || statementIsBreakTarget(loopStatement);
-    }
-    else if (statement instanceof PsiSynchronizedStatement) {
-      final PsiCodeBlock body =
-        ((PsiSynchronizedStatement)statement).getBody();
-      return codeBlockMayCompleteNormally(body);
-    }
-    else if (statement instanceof PsiBlockStatement) {
-      final PsiCodeBlock codeBlock =
-        ((PsiBlockStatement)statement).getCodeBlock();
-      return codeBlockMayCompleteNormally(codeBlock);
-    }
-    else if (statement instanceof PsiLabeledStatement) {
-      final PsiLabeledStatement labeledStatement =
-        (PsiLabeledStatement)statement;
-      final PsiStatement body = labeledStatement.getStatement();
-      return statementMayCompleteNormally(body)
-             || statementIsBreakTarget(body);
-    }
-    else if (statement instanceof PsiIfStatement) {
-      final PsiIfStatement ifStatement = (PsiIfStatement)statement;
-      final PsiStatement thenBranch = ifStatement.getThenBranch();
-      if (statementMayCompleteNormally(thenBranch)) {
-        return true;
-      }
-      final PsiStatement elseBranch = ifStatement.getElseBranch();
-      return elseBranch == null ||
-             statementMayCompleteNormally(elseBranch);
-    }
-    else if (statement instanceof PsiTryStatement) {
-      final PsiTryStatement tryStatement = (PsiTryStatement)statement;
-
-      final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
-      if (finallyBlock != null) {
-        if (!codeBlockMayCompleteNormally(finallyBlock)) {
-          return false;
-        }
-      }
-      final PsiCodeBlock tryBlock = tryStatement.getTryBlock();
-      if (codeBlockMayCompleteNormally(tryBlock)) {
-        return true;
-      }
-      final PsiCodeBlock[] catchBlocks = tryStatement.getCatchBlocks();
-      for (final PsiCodeBlock catchBlock : catchBlocks) {
-        if (codeBlockMayCompleteNormally(catchBlock)) {
-          return true;
-        }
-      }
-      return false;
-    }
-    else if (statement instanceof PsiSwitchStatement) {
-      final PsiSwitchStatement switchStatement =
-        (PsiSwitchStatement)statement;
-      if (statementIsBreakTarget(switchStatement)) {
-        return true;
-      }
-      final PsiCodeBlock body = switchStatement.getBody();
-      if (body == null) {
-        return true;
-      }
-      final PsiStatement[] statements = body.getStatements();
-      int lastNonLabelOffset = -1;
-      final int lastStatementIndex = statements.length - 1;
-      for (int i = lastStatementIndex; i >= 0; i--) {
-        if (!(statements[i] instanceof PsiSwitchLabelStatement)) {
-          lastNonLabelOffset = i;
-          break;
-        }
-      }
-      if (lastNonLabelOffset == -1) {
-        return true;    // it's all labels
-      }
-      else if (lastNonLabelOffset == lastStatementIndex) {
-        return statementMayCompleteNormally(
-          statements[lastStatementIndex]);
-      }
-      else {
-        return true;    // the last statement is a label
-      }
-    }
-    else {
-      return false;
-    }
-  }
-
-  private static boolean codeBlockMayCompleteNormally(PsiCodeBlock block) {
-    if (block == null) {
-      return true;
-    }
-    final PsiStatement[] statements = block.getStatements();
-    for (final PsiStatement statement : statements) {
-      if (!statementMayCompleteNormally(statement)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  private static boolean isBooleanConstant(PsiExpression expression,
-                                           boolean b) {
-    if (expression == null) {
-      return false;
-    }
-    final Project project = expression.getProject();
-    final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
-    final PsiConstantEvaluationHelper constantEvaluationHelper =
-      psiFacade.getConstantEvaluationHelper();
-    final Object value =
-      constantEvaluationHelper.computeConstantExpression
-        (expression, false);
-    if (!(value instanceof Boolean)) {
-      return false;
-    }
-    final Boolean aBoolean = (Boolean)value;
-    return aBoolean.booleanValue() == b;
-  }
-
-  private static boolean statementIsBreakTarget(PsiStatement statement) {
-    if (statement == null) {
-      return false;
-    }
-    final BreakTargetFinder breakFinder = new BreakTargetFinder(statement);
-    statement.accept(breakFinder);
-    return breakFinder.breakFound();
-  }
-
-  public static boolean statementContainsNakedBreak(PsiStatement statement) {
-    if (statement == null) {
-      return false;
-    }
-    final NakedBreakFinder breakFinder = new NakedBreakFinder();
-    statement.accept(breakFinder);
-    return breakFinder.breakFound();
-  }
-
-  private static class BreakTargetFinder
-    extends JavaRecursiveElementWalkingVisitor {
-
-    private boolean m_found = false;
-    private final PsiStatement m_target;
-
-    private BreakTargetFinder(PsiStatement target) {
-      m_target = target;
-    }
-
-    public boolean breakFound() {
-      return m_found;
-    }
-
-    @Override
-    public void visitElement(PsiElement element) {
-      if (m_found) {
-        return;
-      }
-      super.visitElement(element);
-    }
-
-    @Override
-    public void visitReferenceExpression(
-      PsiReferenceExpression expression) {
-    }
-
-    @Override
-    public void visitBreakStatement(PsiBreakStatement statement) {
-      super.visitBreakStatement(statement);
-      final PsiStatement exitedStatement =
-        statement.findExitedStatement();
-      if (exitedStatement == null) {
-        return;
-      }
-      if (exitedStatement.equals(m_target)) {
-        m_found = true;
-      }
-    }
-  }
-
-  private static class NakedBreakFinder
-    extends JavaRecursiveElementWalkingVisitor {
-
-    private boolean m_found = false;
-
-    public boolean breakFound() {
-      return m_found;
-    }
-
-    @Override
-    public void visitElement(PsiElement element) {
-      if (m_found) {
-        return;
-      }
-      super.visitElement(element);
-    }
-
-    @Override
-    public void visitReferenceExpression(
-      PsiReferenceExpression expression) {
-    }
-
-    @Override
-    public void visitBreakStatement(PsiBreakStatement statement) {
-      if (statement.getLabelIdentifier() != null) {
-        return;
-      }
-      m_found = true;
-    }
-
-    @Override
-    public void visitDoWhileStatement(
-      PsiDoWhileStatement statement) {
-      // don't drill down
-    }
-
-    @Override
-    public void visitForStatement(PsiForStatement statement) {
-      // don't drill down
-    }
-
-    @Override
-    public void visitForeachStatement(PsiForeachStatement statement) {
-      // don't drill down
-    }
-
-    @Override
-    public void visitWhileStatement(PsiWhileStatement statement) {
-      // don't drill down
-    }
-
-    @Override
-    public void visitSwitchStatement(
-      PsiSwitchStatement statement) {
-      // don't drill down
-    }
-  }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/SideEffectChecker.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/SideEffectChecker.java
deleted file mode 100644
index 7940dd7..0000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/SideEffectChecker.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2003-2005 Dave Griffith
- *
- * 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.siyeh.ipp.psiutils;
-
-import com.intellij.psi.*;
-import com.intellij.psi.tree.IElementType;
-
-public class SideEffectChecker {
-
-  private SideEffectChecker() {
-    super();
-  }
-
-  public static boolean mayHaveSideEffects(PsiExpression exp) {
-    final SideEffectsVisitor visitor = new SideEffectsVisitor();
-    exp.accept(visitor);
-    return visitor.mayHaveSideEffects();
-  }
-
-  private static class SideEffectsVisitor extends JavaRecursiveElementWalkingVisitor {
-
-    private boolean mayHaveSideEffects = false;
-
-    @Override
-    public void visitElement(PsiElement element) {
-      if (!mayHaveSideEffects) {
-        super.visitElement(element);
-      }
-    }
-
-    @Override
-    public void visitMethodCallExpression(
-      PsiMethodCallExpression expression) {
-      mayHaveSideEffects = true;
-    }
-
-    @Override
-    public void visitNewExpression(PsiNewExpression expression) {
-      mayHaveSideEffects = true;
-    }
-
-    @Override
-    public void visitAssignmentExpression(
-      PsiAssignmentExpression expression) {
-      mayHaveSideEffects = true;
-    }
-
-    @Override
-    public void visitPrefixExpression(PsiPrefixExpression expression) {
-      super.visitPrefixExpression(expression);
-      final IElementType tokenType = expression.getOperationTokenType();
-
-      if (tokenType.equals(JavaTokenType.PLUSPLUS) ||
-          tokenType.equals(JavaTokenType.MINUSMINUS)) {
-        mayHaveSideEffects = true;
-      }
-    }
-
-    @Override
-    public void visitPostfixExpression(PsiPostfixExpression expression) {
-      super.visitPostfixExpression(expression);
-      final IElementType tokenType = expression.getOperationTokenType();
-
-      if (tokenType.equals(JavaTokenType.PLUSPLUS) ||
-          tokenType.equals(JavaTokenType.MINUSMINUS)) {
-        mayHaveSideEffects = true;
-      }
-    }
-
-    public boolean mayHaveSideEffects() {
-      return mayHaveSideEffects;
-    }
-  }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/VariableAccessUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/VariableAccessUtils.java
deleted file mode 100644
index 2ac8500..0000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/VariableAccessUtils.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright 2009-2014 Bas Leijdekkers
- *
- * 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.siyeh.ipp.psiutils;
-
-import com.intellij.psi.*;
-import com.intellij.psi.tree.IElementType;
-import com.siyeh.ig.psiutils.ComparisonUtils;
-import com.siyeh.ig.psiutils.ParenthesesUtils;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-public class VariableAccessUtils {
-
-  private VariableAccessUtils() {
-  }
-
-  public static boolean isVariableCompared(
-    @NotNull PsiVariable variable, @Nullable PsiExpression expression) {
-    if (!(expression instanceof PsiBinaryExpression)) {
-      return false;
-    }
-    final PsiBinaryExpression binaryExpression =
-      (PsiBinaryExpression)expression;
-    final IElementType tokenType = binaryExpression.getOperationTokenType();
-    if (!ComparisonUtils.isComparisonOperation(tokenType)) {
-      return false;
-    }
-    final PsiExpression lhs = binaryExpression.getLOperand();
-    final PsiExpression rhs = binaryExpression.getROperand();
-    if (rhs == null) {
-      return false;
-    }
-    if (evaluatesToVariable(lhs, variable)) {
-      return true;
-    }
-    else if (evaluatesToVariable(rhs, variable)) {
-      return true;
-    }
-    return false;
-  }
-
-  public static boolean isVariableIncrementOrDecremented(
-    @NotNull PsiVariable variable, @Nullable PsiStatement statement) {
-    if (!(statement instanceof PsiExpressionStatement)) {
-      return false;
-    }
-    final PsiExpressionStatement expressionStatement =
-      (PsiExpressionStatement)statement;
-    PsiExpression expression = expressionStatement.getExpression();
-    expression = ParenthesesUtils.stripParentheses(expression);
-    if (expression instanceof PsiPrefixExpression) {
-      final PsiPrefixExpression prefixExpression =
-        (PsiPrefixExpression)expression;
-      final IElementType tokenType = prefixExpression.getOperationTokenType();
-      if (!tokenType.equals(JavaTokenType.PLUSPLUS) &&
-          !tokenType.equals(JavaTokenType.MINUSMINUS)) {
-        return false;
-      }
-      final PsiExpression operand = prefixExpression.getOperand();
-      return evaluatesToVariable(operand, variable);
-    }
-    else if (expression instanceof PsiPostfixExpression) {
-      final PsiPostfixExpression postfixExpression =
-        (PsiPostfixExpression)expression;
-      final IElementType tokenType = postfixExpression.getOperationTokenType();
-      if (!tokenType.equals(JavaTokenType.PLUSPLUS) &&
-          !tokenType.equals(JavaTokenType.MINUSMINUS)) {
-        return false;
-      }
-      final PsiExpression operand = postfixExpression.getOperand();
-      return evaluatesToVariable(operand, variable);
-    }
-    else if (expression instanceof PsiAssignmentExpression) {
-      final PsiAssignmentExpression assignmentExpression =
-        (PsiAssignmentExpression)expression;
-      final IElementType tokenType =
-        assignmentExpression.getOperationTokenType();
-      PsiExpression lhs = assignmentExpression.getLExpression();
-      lhs = ParenthesesUtils.stripParentheses(lhs);
-      if (!evaluatesToVariable(lhs, variable)) {
-        return false;
-      }
-      PsiExpression rhs = assignmentExpression.getRExpression();
-      rhs = ParenthesesUtils.stripParentheses(rhs);
-      if (tokenType == JavaTokenType.EQ) {
-        if (!(rhs instanceof PsiBinaryExpression)) {
-          return false;
-        }
-        final PsiBinaryExpression binaryExpression =
-          (PsiBinaryExpression)rhs;
-        final IElementType token =
-          binaryExpression.getOperationTokenType();
-        if (!token.equals(JavaTokenType.PLUS) &&
-            !token.equals(JavaTokenType.MINUS)) {
-          return false;
-        }
-        PsiExpression lOperand = binaryExpression.getLOperand();
-        lOperand = ParenthesesUtils.stripParentheses(lOperand);
-        PsiExpression rOperand = binaryExpression.getROperand();
-        rOperand = ParenthesesUtils.stripParentheses(rOperand);
-        if (evaluatesToVariable(rOperand, variable)) {
-          return true;
-        }
-        else if (evaluatesToVariable(lOperand, variable)) {
-          return true;
-        }
-      }
-      else if (tokenType == JavaTokenType.PLUSEQ ||
-               tokenType == JavaTokenType.MINUSEQ) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  public static boolean evaluatesToVariable(
-    @Nullable PsiExpression expression,
-    @NotNull PsiVariable variable) {
-    final PsiExpression strippedExpression =
-      ParenthesesUtils.stripParentheses(expression);
-    if (strippedExpression == null) {
-      return false;
-    }
-    if (!(expression instanceof PsiReferenceExpression)) {
-      return false;
-    }
-    final PsiReferenceExpression referenceExpression =
-      (PsiReferenceExpression)expression;
-    final PsiElement referent = referenceExpression.resolve();
-    return variable.equals(referent);
-  }
-
-  public static boolean isAnyVariableAssigned(
-    @NotNull Collection<PsiVariable> variables,
-    @Nullable PsiElement context) {
-    if (context == null) {
-      return false;
-    }
-    final VariableAssignedVisitor visitor =
-      new VariableAssignedVisitor(variables, true);
-    context.accept(visitor);
-    return visitor.isAssigned();
-  }
-
-  public static Set<PsiVariable> collectUsedVariables(
-    PsiElement context) {
-    if (context == null) {
-      return Collections.emptySet();
-    }
-    final VariableCollectingVisitor visitor =
-      new VariableCollectingVisitor();
-    context.accept(visitor);
-    return visitor.getUsedVariables();
-  }
-
-  private static class VariableCollectingVisitor
-    extends JavaRecursiveElementVisitor {
-
-    private final Set<PsiVariable> usedVariables = new HashSet();
-
-    @Override
-    public void visitReferenceExpression(
-      PsiReferenceExpression expression) {
-      super.visitReferenceExpression(expression);
-      final PsiElement target = expression.resolve();
-      if (!(target instanceof PsiVariable)) {
-        return;
-      }
-      final PsiVariable variable = (PsiVariable)target;
-      usedVariables.add(variable);
-    }
-
-    public Set<PsiVariable> getUsedVariables() {
-      return usedVariables;
-    }
-  }
-}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/VariableAssignedVisitor.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/VariableAssignedVisitor.java
deleted file mode 100644
index 8352feb..0000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/VariableAssignedVisitor.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
- *
- * 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.siyeh.ipp.psiutils;
-
-import com.intellij.psi.*;
-import com.intellij.psi.tree.IElementType;
-import com.siyeh.ig.psiutils.ParenthesesUtils;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Collection;
-
-class VariableAssignedVisitor extends JavaRecursiveElementVisitor {
-
-  @NotNull private final Collection<PsiVariable> variables;
-  private final boolean recurseIntoClasses;
-  private boolean assigned = false;
-
-  public VariableAssignedVisitor(@NotNull Collection<PsiVariable> variables,
-                                 boolean recurseIntoClasses) {
-    this.variables = variables;
-    this.recurseIntoClasses = recurseIntoClasses;
-  }
-
-  @Override
-  public void visitElement(@NotNull PsiElement element) {
-    if (assigned) {
-      return;
-    }
-    super.visitElement(element);
-  }
-
-  @Override
-  public void visitAssignmentExpression(
-    @NotNull PsiAssignmentExpression assignment) {
-    if (assigned) {
-      return;
-    }
-    super.visitAssignmentExpression(assignment);
-    final PsiExpression lhs = assignment.getLExpression();
-    for (PsiVariable variable : variables) {
-      if (mayEvaluateToVariable(lhs, variable)) {
-        assigned = true;
-      }
-    }
-  }
-
-  @Override
-  public void visitClass(PsiClass aClass) {
-    if (!recurseIntoClasses) {
-      return;
-    }
-    if (assigned) {
-      return;
-    }
-    super.visitClass(aClass);
-  }
-
-  @Override
-  public void visitPrefixExpression(
-    @NotNull PsiPrefixExpression prefixExpression) {
-    if (assigned) {
-      return;
-    }
-    super.visitPrefixExpression(prefixExpression);
-    final IElementType tokenType = prefixExpression.getOperationTokenType();
-    if (!tokenType.equals(JavaTokenType.PLUSPLUS) &&
-        !tokenType.equals(JavaTokenType.MINUSMINUS)) {
-      return;
-    }
-    final PsiExpression operand = prefixExpression.getOperand();
-    for (PsiVariable variable : variables) {
-      if (mayEvaluateToVariable(operand, variable)) {
-        assigned = true;
-      }
-    }
-  }
-
-  @Override
-  public void visitPostfixExpression(
-    @NotNull PsiPostfixExpression postfixExpression) {
-    if (assigned) {
-      return;
-    }
-    super.visitPostfixExpression(postfixExpression);
-    final IElementType tokenType = postfixExpression.getOperationTokenType();
-    if (!tokenType.equals(JavaTokenType.PLUSPLUS) &&
-        !tokenType.equals(JavaTokenType.MINUSMINUS)) {
-      return;
-    }
-    final PsiExpression operand = postfixExpression.getOperand();
-    for (PsiVariable variable : variables) {
-      if (mayEvaluateToVariable(operand, variable)) {
-        assigned = true;
-      }
-    }
-  }
-
-  public static boolean mayEvaluateToVariable(
-    @Nullable PsiExpression expression,
-    @NotNull PsiVariable variable) {
-    if (expression == null) {
-      return false;
-    }
-    if (expression instanceof PsiBinaryExpression) {
-      final PsiBinaryExpression binaryExpression =
-        (PsiBinaryExpression)expression;
-      final PsiExpression lOperand = binaryExpression.getLOperand();
-      final PsiExpression rOperand = binaryExpression.getROperand();
-      return mayEvaluateToVariable(lOperand, variable) ||
-             mayEvaluateToVariable(rOperand, variable);
-    }
-    if (expression instanceof PsiParenthesizedExpression) {
-      final PsiParenthesizedExpression parenthesizedExpression =
-        (PsiParenthesizedExpression)expression;
-      final PsiExpression containedExpression =
-        parenthesizedExpression.getExpression();
-      return mayEvaluateToVariable(containedExpression, variable);
-    }
-    if (expression instanceof PsiTypeCastExpression) {
-      final PsiTypeCastExpression typeCastExpression =
-        (PsiTypeCastExpression)expression;
-      final PsiExpression containedExpression =
-        typeCastExpression.getOperand();
-      return mayEvaluateToVariable(containedExpression, variable);
-    }
-    if (expression instanceof PsiConditionalExpression) {
-      final PsiConditionalExpression conditional =
-        (PsiConditionalExpression)expression;
-      final PsiExpression thenExpression = conditional.getThenExpression();
-      final PsiExpression elseExpression = conditional.getElseExpression();
-      return mayEvaluateToVariable(thenExpression, variable) ||
-             mayEvaluateToVariable(elseExpression, variable);
-    }
-    if (expression instanceof PsiArrayAccessExpression) {
-      final PsiElement parent = expression.getParent();
-      if (parent instanceof PsiArrayAccessExpression) {
-        return false;
-      }
-      final PsiType type = variable.getType();
-      if (!(type instanceof PsiArrayType)) {
-        return false;
-      }
-      final PsiArrayType arrayType = (PsiArrayType)type;
-      final int dimensions = arrayType.getArrayDimensions();
-      if (dimensions <= 1) {
-        return false;
-      }
-      PsiArrayAccessExpression arrayAccessExpression =
-        (PsiArrayAccessExpression)expression;
-      PsiExpression arrayExpression =
-        arrayAccessExpression.getArrayExpression();
-      int count = 1;
-      while (arrayExpression instanceof PsiArrayAccessExpression) {
-        arrayAccessExpression =
-          (PsiArrayAccessExpression)arrayExpression;
-        arrayExpression = arrayAccessExpression.getArrayExpression();
-        count++;
-      }
-      return count != dimensions &&
-             mayEvaluateToVariable(arrayExpression, variable);
-    }
-    return evaluatesToVariable(expression, variable);
-  }
-
-  public static boolean evaluatesToVariable(
-    @Nullable PsiExpression expression,
-    @NotNull PsiVariable variable) {
-    final PsiExpression strippedExpression =
-      ParenthesesUtils.stripParentheses(expression);
-    if (strippedExpression == null) {
-      return false;
-    }
-    if (!(expression instanceof PsiReferenceExpression)) {
-      return false;
-    }
-    final PsiReferenceExpression referenceExpression =
-      (PsiReferenceExpression)expression;
-    final PsiElement referent = referenceExpression.resolve();
-    return variable.equals(referent);
-  }
-
-  public boolean isAssigned() {
-    return assigned;
-  }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchIntention.java
index cde03e1..9f40b4b 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchIntention.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,12 +18,12 @@
 import com.intellij.psi.*;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiTreeUtil;
+import com.siyeh.ig.psiutils.ControlFlowUtils;
 import com.siyeh.ig.psiutils.EquivalenceChecker;
 import com.siyeh.ig.psiutils.SwitchUtils;
 import com.siyeh.ig.psiutils.SwitchUtils.IfStatementBranch;
 import com.siyeh.ipp.base.Intention;
 import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ControlFlowUtils;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfOrPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfOrPredicate.java
index b2c5aa8..3dfd039 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfOrPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfOrPredicate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2012 Dave Griffith
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,9 +17,9 @@
 
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiTreeUtil;
+import com.siyeh.ig.psiutils.ControlFlowUtils;
 import com.siyeh.ig.psiutils.EquivalenceChecker;
 import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ControlFlowUtils;
 import com.siyeh.ipp.psiutils.ErrorUtil;
 
 class MergeIfOrPredicate implements PsiElementPredicate {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeParallelIfsPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeParallelIfsPredicate.java
index f2e8893..57a7891 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeParallelIfsPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeParallelIfsPredicate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,11 +17,11 @@
 
 import com.intellij.psi.*;
 import com.intellij.psi.util.PsiTreeUtil;
+import com.siyeh.ig.psiutils.ControlFlowUtils;
 import com.siyeh.ig.psiutils.EquivalenceChecker;
+import com.siyeh.ig.psiutils.VariableAccessUtils;
 import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ControlFlowUtils;
 import com.siyeh.ipp.psiutils.ErrorUtil;
-import com.siyeh.ipp.psiutils.VariableAccessUtils;
 
 import java.util.Collection;
 import java.util.HashSet;
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/BetweenIfAndElse.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/BetweenIfAndElse.java
new file mode 100644
index 0000000..0065809
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/BetweenIfAndElse.java
@@ -0,0 +1,10 @@
+class X {
+  {
+    if (true) {
+      System.out.println();
+    }
+<caret>    else {
+      System.out.println();
+    }
+  }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse.java
new file mode 100644
index 0000000..29a5958
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse.java
@@ -0,0 +1,10 @@
+class X {
+  {
+    if (true) {
+      System.out.println();
+    }<caret>
+    else {
+      System.out.println();
+    }
+  }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse2.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse2.java
new file mode 100644
index 0000000..9815cdf
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse2.java
@@ -0,0 +1,10 @@
+class X {
+  {
+    if<caret> (true) {
+      System.out.println();
+    }
+    else {
+      System.out.println();
+    }
+  }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse2_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse2_after.java
new file mode 100644
index 0000000..feae026
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse2_after.java
@@ -0,0 +1,8 @@
+class X {
+  {
+    if (true) System.out.println();
+    else {
+      System.out.println();
+    }
+  }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse_after.java
new file mode 100644
index 0000000..feae026
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/braces/remove/IfElse_after.java
@@ -0,0 +1,8 @@
+class X {
+  {
+    if (true) System.out.println();
+    else {
+      System.out.println();
+    }
+  }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/braces/RemoveBracesIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/braces/RemoveBracesIntentionTest.java
new file mode 100644
index 0000000..74ebd04
--- /dev/null
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/braces/RemoveBracesIntentionTest.java
@@ -0,0 +1,39 @@
+/*
+  * 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.
+  * 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.siyeh.ipp.braces;
+
+import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ipp.IPPTestCase;
+
+/**
+ * @see RemoveBracesIntention
+ * @author Bas Leijdekkers
+ */
+public class RemoveBracesIntentionTest extends IPPTestCase {
+  @Override
+  protected String getRelativePath() {
+    return "braces/remove";
+  }
+
+  @Override
+  protected String getIntentionName() {
+    return IntentionPowerPackBundle.message("remove.braces.intention.name", "if");
+  }
+
+  public void testBetweenIfAndElse() { assertIntentionNotAvailable(RemoveBracesIntention.class);}
+  public void testIfElse() { doTest(); }
+  public void testIfElse2() { doTest(); }
+}
diff --git a/plugins/ant/jps-plugin/ant-jps-plugin.iml b/plugins/ant/jps-plugin/ant-jps-plugin.iml
index 976f684..12aeb83 100644
--- a/plugins/ant/jps-plugin/ant-jps-plugin.iml
+++ b/plugins/ant/jps-plugin/ant-jps-plugin.iml
@@ -13,6 +13,7 @@
     <orderEntry type="module" module-name="util" />
     <orderEntry type="module" module-name="jps-builders" />
     <orderEntry type="module" module-name="java-runtime" />
+    <orderEntry type="module" module-name="jps-serialization-tests" scope="TEST" />
   </component>
 </module>
 
diff --git a/plugins/ant/src/com/intellij/lang/ant/AntImportsIndex.java b/plugins/ant/src/com/intellij/lang/ant/AntImportsIndex.java
index be3dc67..6c8e413 100644
--- a/plugins/ant/src/com/intellij/lang/ant/AntImportsIndex.java
+++ b/plugins/ant/src/com/intellij/lang/ant/AntImportsIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -98,11 +98,13 @@
     return DATA_INDEXER;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<Integer> getKeyDescriptor() {
     return EnumeratorIntegerDescriptor.INSTANCE;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return new DefaultFileTypeSpecificInputFilter(StdFileTypes.XML);
diff --git a/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/CvsBundle.properties b/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/CvsBundle.properties
index 8938506..15ce261 100644
--- a/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/CvsBundle.properties
+++ b/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/CvsBundle.properties
@@ -415,7 +415,6 @@
 action.Cvs.ToggleOffline.description=Toggle offline mode for CVS root containing selected file
 set.online.notification.text=Set to online mode
 set.offline.notification.text=Set to offline mode
-plugin.CVS.description=Provides integration with CVS version control system
 adding.cvsignore.files.to.cvs.action.name=Adding .cvsignore Files to CVS
 browse.repository.operation.name=Browse Repository
 configure.global.cvs.settings.action.name=Configure Global CVS Settings
diff --git a/plugins/cvs/cvs-plugin/src/META-INF/plugin.xml b/plugins/cvs/cvs-plugin/src/META-INF/plugin.xml
index 20f34c5..1cefc97 100644
--- a/plugins/cvs/cvs-plugin/src/META-INF/plugin.xml
+++ b/plugins/cvs/cvs-plugin/src/META-INF/plugin.xml
@@ -5,6 +5,17 @@
   <vendor>JetBrains</vendor>
   <resource-bundle>com.intellij.cvsSupport2.CvsBundle</resource-bundle>
   <category>VCS Integration</category>
+  <description>
+      <![CDATA[
+      Allows working with CVS version control system.
+      The following features are available:
+        <ul>
+        <li>Dedicated page under the Version Control node in the Settings/Preferences dialog.</li>
+        <li>When CVS is not enabled, it is still possible to browse, check out sources from and import into the available CVS repositories.</li>
+        <li>When CVS is enabled, the CVS node appears on the VCS menu, and on the context menu of the editor.
+        </ul>
+      ]]>
+   </description>
 
   <depends>com.intellij.modules.lang</depends>
   <depends>com.intellij.modules.vcs</depends>
diff --git a/plugins/devkit/jps-plugin/devkit-jps-plugin.iml b/plugins/devkit/jps-plugin/devkit-jps-plugin.iml
index f88b075..a80f7f3 100644
--- a/plugins/devkit/jps-plugin/devkit-jps-plugin.iml
+++ b/plugins/devkit/jps-plugin/devkit-jps-plugin.iml
@@ -12,6 +12,7 @@
     <orderEntry type="module" module-name="jps-model-serialization" />
     <orderEntry type="module" module-name="jps-builders" />
     <orderEntry type="module" module-name="jps-model-impl" scope="TEST" />
+    <orderEntry type="module" module-name="jps-serialization-tests" scope="TEST" />
   </component>
 </module>
 
diff --git a/plugins/devkit/src/references/IconsReferencesContributor.java b/plugins/devkit/src/references/IconsReferencesContributor.java
index 74d2587..eac85d8 100644
--- a/plugins/devkit/src/references/IconsReferencesContributor.java
+++ b/plugins/devkit/src/references/IconsReferencesContributor.java
@@ -299,7 +299,7 @@
         model.setCaseSensitive(true);
         model.setFindAll(true);
         model.setWholeWordsOnly(true);
-        FindInProjectUtil.findUsages(model, FindInProjectUtil.getPsiDirectory(model, project), project, false, new Processor<UsageInfo>() {
+        FindInProjectUtil.findUsages(model, FindInProjectUtil.getPsiDirectory(model, project), project, new Processor<UsageInfo>() {
           @Override
           public boolean process(final UsageInfo usage) {
             ApplicationManager.getApplication().runReadAction(new Runnable() {
diff --git a/plugins/eclipse/resources/META-INF/plugin.xml b/plugins/eclipse/resources/META-INF/plugin.xml
index b3cd54d..a3f7650 100644
--- a/plugins/eclipse/resources/META-INF/plugin.xml
+++ b/plugins/eclipse/resources/META-INF/plugin.xml
@@ -1,7 +1,20 @@
 <idea-plugin>
   <name>Eclipse Integration</name>
   <id>org.jetbrains.idea.eclipse</id>
-  <description>Provides possibility to import, export and synchronize Eclipse project files</description>
+  <description>
+      <![CDATA[
+        This plugin enables integration with Eclipse and provides the following features:
+        <ul>
+        <li>Open Eclipse project in IntelliJ IDEA</li>
+        <li>Import Eclipse project into IntelliJ IDEA</li>
+        <li>Export IntelliJ IDEA project into Eclipse</li>
+        <li>Convert IntelliJ IDEA module to Eclipse-compatible format</li>
+        <li>Synchronize Eclipse project files</li>
+        </ul>
+        <p/>
+      ]]>
+    </description>
+
   <version>3.0</version>
   <vendor url="http://www.jetbrains.com" logo="/general/ijLogo.png">JetBrains s.r.o.</vendor>
   <extensions defaultExtensionNs="com.intellij">
diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentChecker.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentChecker.java
index 155e7e2..df40458 100644
--- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentChecker.java
+++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentChecker.java
@@ -16,7 +16,6 @@
 package com.intellij.remoteServer.util;
 
 import com.intellij.execution.configurations.RuntimeConfigurationWarning;
-import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.module.Module;
 import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.openapi.project.Project;
@@ -29,14 +28,11 @@
 import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
 import com.intellij.remoteServer.configuration.deployment.ModuleDeploymentSource;
 import git4idea.GitUtil;
-import git4idea.commands.Git;
-import git4idea.repo.GitRemote;
 import git4idea.repo.GitRepository;
 import git4idea.repo.GitRepositoryManager;
 
 import java.io.File;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.util.List;
 
 /**
  * @author michael.golubev
@@ -47,21 +43,23 @@
   SR extends CloudMultiSourceServerRuntimeInstance<T, ?, ?, ?>> {
 
   private GitRepositoryManager myGitRepositoryManager;
-  private Git myGit;
 
   private final DeploymentSource myDeploymentSource;
   private final RemoteServer<SC> myServer;
   private final CloudDeploymentNameEditor<T> mySettingsEditor;
+  private final CloudGitDeploymentDetector myDetector;
 
   public CloudGitDeploymentChecker(DeploymentSource deploymentSource,
                                    RemoteServer<SC> server,
-                                   CloudDeploymentNameEditor<T> settingsEditor) {
+                                   CloudDeploymentNameEditor<T> settingsEditor,
+                                   CloudGitDeploymentDetector detector) {
     myDeploymentSource = deploymentSource;
     myServer = server;
     mySettingsEditor = settingsEditor;
+    myDetector = detector;
   }
 
-  public void checkGitUrl(final T settings, Pattern gitUrlPattern) throws ConfigurationException {
+  public void checkGitUrl(final T settings) throws ConfigurationException {
     if (!(myDeploymentSource instanceof ModuleDeploymentSource)) {
       return;
     }
@@ -82,12 +80,6 @@
     if (myGitRepositoryManager == null) {
       myGitRepositoryManager = GitUtil.getRepositoryManager(project);
     }
-    if (myGit == null) {
-      myGit = ServiceManager.getService(Git.class);
-      if (myGit == null) {
-        return;
-      }
-    }
 
     VirtualFile contentRoot = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(contentRootFile);
     if (contentRoot == null) {
@@ -102,28 +94,11 @@
 
     String expectedName = settings.getDeploymentSourceName(myDeploymentSource);
 
-    boolean unexpectedNameFound = false;
-    for (GitRemote remote : repository.getRemotes()) {
-      for (String url : remote.getUrls()) {
-        Matcher matcher = gitUrlPattern.matcher(url);
-        if (matcher.matches()) {
-          String matchedName = matcher.group(1);
-          if (matchedName.equals(expectedName)) {
-            return;
-          }
-          else {
-            unexpectedNameFound = true;
-            break;
-          }
-        }
-      }
-    }
-
-    if (!unexpectedNameFound) {
+    List<String> appNames = myDetector.collectApplicationNames(repository);
+    if (appNames.isEmpty() || appNames.contains(expectedName)) {
       return;
     }
 
-
     RuntimeConfigurationWarning warning =
       new RuntimeConfigurationWarning("Cloud Git URL found in repository, but it doesn't match the run configuration");
 
diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentDetector.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentDetector.java
new file mode 100644
index 0000000..f4fdd3f
--- /dev/null
+++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentDetector.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.remoteServer.util;
+
+import git4idea.repo.GitRemote;
+import git4idea.repo.GitRepository;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author michael.golubev
+ */
+public class CloudGitDeploymentDetector {
+
+  private final Pattern myGitUrlPattern;
+
+  public CloudGitDeploymentDetector(Pattern gitUrlPattern) {
+    myGitUrlPattern = gitUrlPattern;
+  }
+
+  public List<String> collectApplicationNames(@NotNull GitRepository repository) {
+    List<String> result = new ArrayList<String>();
+    for (GitRemote remote : repository.getRemotes()) {
+      for (String url : remote.getUrls()) {
+        Matcher matcher = myGitUrlPattern.matcher(url);
+        if (matcher.matches()) {
+          result.add(matcher.group(1));
+        }
+      }
+    }
+    return result;
+  }
+}
diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml
index 5bd07d3..8664c8a 100644
--- a/plugins/git4idea/src/META-INF/plugin.xml
+++ b/plugins/git4idea/src/META-INF/plugin.xml
@@ -1,7 +1,18 @@
 <idea-plugin>
   <name>Git Integration</name>
   <id>Git4Idea</id>
-  <description>Provides integration with Git version control system</description>
+  <description>
+      <![CDATA[
+      Allows working with <a href="http://git-scm.com/">Git version control system</a>.
+      The following features are available:
+        <ul>
+        <li>Dedicated page under the Version Control node in the Settings/Preferences dialog.</li>
+        <li>Ability to browse, check out sources from and import into the available Git repositories, when Git is not enabled.</li>
+        <li>When Git is enabled, the Git node appears on the VCS menu, and on the context menu of the editor.</li>
+        </ul>
+         <p>Numerous plugins depend on the Git Integration plugin.</p>
+      ]]>
+   </description>
   <version>8.1</version>
   <category>VCS Integration</category>
   <vendor url="http://svn.jetbrains.org/idea/Trunk/bundled/git4idea/" logo="/general/ijLogo.png">JetBrains</vendor>
diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
index d5c4b3f..013d4ca 100644
--- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
+++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
@@ -25,7 +25,10 @@
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vcs.*;
+import com.intellij.openapi.vcs.CheckinProjectPanel;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.ObjectsConvertor;
+import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.changes.*;
 import com.intellij.openapi.vcs.changes.ui.SelectFilePathsDialog;
 import com.intellij.openapi.vcs.checkin.CheckinChangeListSpecificComponent;
@@ -33,7 +36,10 @@
 import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.GuiUtils;
-import com.intellij.util.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.FunctionUtil;
+import com.intellij.util.NullableFunction;
+import com.intellij.util.PairConsumer;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.Convertor;
 import com.intellij.util.ui.UIUtil;
@@ -643,8 +649,8 @@
 
     @Override
     @NotNull
-    protected Set<VirtualFile> getRoots() {
-      return GitUtil.gitRoots(getSelectedFilePaths());
+    protected Set<VirtualFile> getVcsRoots(@NotNull Collection<FilePath> filePaths) {
+      return GitUtil.gitRoots(filePaths);
     }
 
     @Nullable
@@ -665,26 +671,18 @@
       return h.run();
     }
 
-    @NotNull
-    private List<FilePath> getSelectedFilePaths() {
-      return ContainerUtil.map(myCheckinPanel.getFiles(), new Function<File, FilePath>() {
-        @Override
-        public FilePath fun(File file) {
-          return new FilePathImpl(file, file.isDirectory());
-        }
-      });
-    }
-
     private List<String> getUsersList(final Project project) {
       return NewGitUsersComponent.getInstance(project).get();
     }
 
+    @Override
     public void refresh() {
       super.refresh();
       myAuthor.setSelectedItem("");
       reset();
     }
 
+    @Override
     public void saveState() {
       String author = (String)myAuthor.getEditor().getItem();
       myNextCommitAuthor = author.length() == 0 ? null : author;
@@ -699,6 +697,7 @@
       myNextCommitAuthorDate = myAuthorDate;
     }
 
+    @Override
     public void restoreState() {
       refresh();
     }
diff --git a/plugins/git4idea/src/git4idea/history/NewGitUsersComponent.java b/plugins/git4idea/src/git4idea/history/NewGitUsersComponent.java
index 2afb3c8..89ccaa5 100644
--- a/plugins/git4idea/src/git4idea/history/NewGitUsersComponent.java
+++ b/plugins/git4idea/src/git4idea/history/NewGitUsersComponent.java
@@ -1,9 +1,12 @@
 /*
- * Copyright 2000-2010 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.
  * 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.
@@ -88,7 +91,7 @@
 
   private static class MyDataExternalizer implements DataExternalizer<List<String>> {
     @Override
-    public List<String> read(DataInput in) throws IOException {
+    public List<String> read(@NotNull DataInput in) throws IOException {
       final int size = in.readInt();
       final ArrayList<String> result = new ArrayList<String>(size);
       for (int i = 0; i < size; i++) {
@@ -98,7 +101,7 @@
     }
 
     @Override
-    public void save(DataOutput out, List<String> value) throws IOException {
+    public void save(@NotNull DataOutput out, List<String> value) throws IOException {
       out.writeInt(value.size());
       for (String s : value) {
         out.writeUTF(s);
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/GitCommitsSequentialIndex.java b/plugins/git4idea/src/git4idea/history/wholeTree/GitCommitsSequentialIndex.java
index 70239c1..0c69e45 100644
--- a/plugins/git4idea/src/git4idea/history/wholeTree/GitCommitsSequentialIndex.java
+++ b/plugins/git4idea/src/git4idea/history/wholeTree/GitCommitsSequentialIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -39,6 +39,7 @@
 import git4idea.GitRevisionNumber;
 import git4idea.history.GitHistoryUtils;
 import git4idea.history.browser.SHAHash;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.*;
 import java.util.*;
@@ -120,12 +121,12 @@
   private DataExternalizer<String> createExternalizer() {
     return new DataExternalizer<String>() {
       @Override
-      public void save(DataOutput out, String value) throws IOException {
+      public void save(@NotNull DataOutput out, String value) throws IOException {
         out.writeUTF(value);
       }
 
       @Override
-      public String read(DataInput in) throws IOException {
+      public String read(@NotNull DataInput in) throws IOException {
         return in.readUTF();
       }
     };
diff --git a/plugins/git4idea/tests/git4idea/tests/SkeletonBuilderTest.java b/plugins/git4idea/tests/git4idea/tests/SkeletonBuilderTest.java
index aabf48c..1417a11 100644
--- a/plugins/git4idea/tests/git4idea/tests/SkeletonBuilderTest.java
+++ b/plugins/git4idea/tests/git4idea/tests/SkeletonBuilderTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -789,6 +789,7 @@
       return new MockVirtualFileSystem();
     }
 
+    @NotNull
     @Override
     public String getPath() {
       return "mock";
diff --git a/plugins/github/src/META-INF/plugin.xml b/plugins/github/src/META-INF/plugin.xml
index e034563..8baf48b 100644
--- a/plugins/github/src/META-INF/plugin.xml
+++ b/plugins/github/src/META-INF/plugin.xml
@@ -2,7 +2,17 @@
   <name>GitHub</name>
   <id>org.jetbrains.plugins.github</id>
   <vendor>JetBrains</vendor>
-  <description>GitHub integration</description>
+  <description>
+      <![CDATA[
+      Allows working with <a href="http://github.com/">GitHub</a>.
+      The following features are available:
+        <ul>
+        <li>Dedicated page under the Version Control node in the Settings/Preferences dialog.</li>
+        <li>Ability to browse, check out sources from and import into the available Git repositories, when GitHub is not enabled.</li>
+        <li>When GitHub is enabled, the GitHub node appears on the VCS menu, and on the context menu of the editor.
+        </ul>
+      ]]>
+   </description>
 
   <depends>com.intellij.modules.lang</depends>
   <depends>Git4Idea</depends>
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java
index 878b9b8..600f484 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java
@@ -29,6 +29,7 @@
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.changes.ChangeListManager;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -41,12 +42,14 @@
 import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
 import org.jetbrains.plugins.github.ui.GithubCreateGistDialog;
 import org.jetbrains.plugins.github.util.GithubAuthData;
+import org.jetbrains.plugins.github.util.GithubAuthDataHolder;
 import org.jetbrains.plugins.github.util.GithubNotifications;
 import org.jetbrains.plugins.github.util.GithubUtil;
 
 import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 import static org.jetbrains.plugins.github.api.GithubGist.FileContent;
 
@@ -110,33 +113,24 @@
       return;
     }
 
-    GithubAuthData auth = GithubAuthData.createAnonymous();
-    if (!dialog.isAnonymous()) {
-      try {
-        auth = getValidAuthData(project);
-      }
-      catch (GithubOperationCanceledException e) {
-        return;
-      }
-      catch (IOException e) {
-        GithubNotifications.showError(project, "Can't create gist", e);
-        return;
-      }
+    final GithubAuthDataHolder authHolder = getValidAuthData(project, dialog.isAnonymous());
+    if (authHolder == null) {
+      return;
     }
 
-    final AtomicReference<String> url = new AtomicReference<String>();
-    final GithubAuthData finalAuth = auth;
+    final Ref<String> url = new Ref<String>();
     new Task.Backgroundable(project, "Creating Gist...") {
       @Override
       public void run(@NotNull ProgressIndicator indicator) {
         List<FileContent> contents = collectContents(project, editor, file, files);
-        String gistUrl = createGist(project, finalAuth, contents, dialog.isPrivate(), dialog.getDescription(), dialog.getFileName());
+        String gistUrl =
+          createGist(project, authHolder, indicator, contents, dialog.isPrivate(), dialog.getDescription(), dialog.getFileName());
         url.set(gistUrl);
       }
 
       @Override
       public void onSuccess() {
-        if (url.get() == null) {
+        if (url.isNull()) {
           return;
         }
         if (dialog.isOpenInBrowser()) {
@@ -149,17 +143,32 @@
     }.queue();
   }
 
-  @NotNull
-  private static GithubAuthData getValidAuthData(@NotNull final Project project) throws IOException {
-    return GithubUtil.computeValueInModal(project, "Access to GitHub",
-                                          new ThrowableConvertor<ProgressIndicator, GithubAuthData, IOException>() {
-                                            @NotNull
-                                            @Override
-                                            public GithubAuthData convert(ProgressIndicator indicator) throws IOException {
-                                              return GithubUtil.getValidAuthDataFromConfig(project, indicator);
-                                            }
-                                          }
-    );
+  @Nullable
+  private static GithubAuthDataHolder getValidAuthData(@NotNull final Project project, boolean isAnonymous) {
+    if (isAnonymous) {
+      return new GithubAuthDataHolder(GithubAuthData.createAnonymous());
+    }
+    else {
+      try {
+        return GithubUtil
+          .computeValueInModal(project, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, GithubAuthDataHolder, IOException>() {
+                                 @NotNull
+                                 @Override
+                                 public GithubAuthDataHolder convert(ProgressIndicator indicator) throws IOException {
+                                   return GithubUtil.getValidAuthDataHolderFromConfig(project, indicator);
+                                 }
+                               }
+          );
+      }
+      catch (GithubOperationCanceledException e) {
+        return null;
+      }
+      catch (IOException e) {
+        GithubNotifications.showError(project, "Can't create gist", e);
+        return null;
+      }
+
+    }
   }
 
   @NotNull
@@ -197,10 +206,11 @@
 
   @Nullable
   static String createGist(@NotNull Project project,
-                           @NotNull GithubAuthData auth,
+                           @NotNull GithubAuthDataHolder auth,
+                           @NotNull ProgressIndicator indicator,
                            @NotNull List<FileContent> contents,
-                           boolean isPrivate,
-                           @NotNull String description,
+                           final boolean isPrivate,
+                           @NotNull final String description,
                            @Nullable String filename) {
     if (contents.isEmpty()) {
       GithubNotifications.showWarning(project, FAILED_TO_CREATE_GIST, "Can't create empty gist");
@@ -211,8 +221,14 @@
       contents = Collections.singletonList(new FileContent(filename, entry.getContent()));
     }
     try {
-      GithubGist gist = GithubApiUtil.createGist(auth, contents, description, isPrivate);
-      return gist.getHtmlUrl();
+      final List<FileContent> finalContents = contents;
+      return GithubUtil.runTask(project, auth, indicator, new ThrowableConvertor<GithubAuthData, GithubGist, IOException>() {
+        @NotNull
+        @Override
+        public GithubGist convert(@NotNull GithubAuthData auth) throws IOException {
+          return GithubApiUtil.createGist(auth, finalContents, description, isPrivate);
+        }
+      }).getHtmlUrl();
     }
     catch (IOException e) {
       GithubNotifications.showError(project, FAILED_TO_CREATE_GIST, e);
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java
index ee357b1..d06851c 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java
@@ -8,6 +8,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.changes.Change;
@@ -37,17 +38,13 @@
 import org.jetbrains.plugins.github.api.*;
 import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
 import org.jetbrains.plugins.github.ui.GithubSelectForkDialog;
-import org.jetbrains.plugins.github.util.GithubAuthData;
-import org.jetbrains.plugins.github.util.GithubNotifications;
-import org.jetbrains.plugins.github.util.GithubUrlUtil;
-import org.jetbrains.plugins.github.util.GithubUtil;
+import org.jetbrains.plugins.github.util.*;
 
 import java.io.IOException;
 import java.util.*;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.FutureTask;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * @author Aleksey Pivovarov
@@ -63,7 +60,7 @@
   @NotNull private final String myRemoteName;
   @NotNull private final String myRemoteUrl;
   @NotNull private final String myCurrentBranch;
-  @NotNull private final GithubAuthData myAuth;
+  @NotNull private final GithubAuthDataHolder myAuthHolder;
 
   @NotNull private final Map<String, FutureTask<DiffInfo>> myDiffInfos;
 
@@ -77,7 +74,7 @@
                                         @NotNull String remoteName,
                                         @NotNull String remoteUrl,
                                         @NotNull String currentBranch,
-                                        @NotNull GithubAuthData auth) {
+                                        @NotNull GithubAuthDataHolder authHolder) {
     myProject = project;
     myGit = git;
     myGitRepository = gitRepository;
@@ -85,7 +82,7 @@
     myRemoteName = remoteName;
     myRemoteUrl = remoteUrl;
     myCurrentBranch = currentBranch;
-    myAuth = auth;
+    myAuthHolder = authHolder;
 
     myDiffInfos = new HashMap<String, FutureTask<DiffInfo>>();
   }
@@ -134,14 +131,14 @@
       return null;
     }
 
-    GithubAuthData auth;
+    GithubAuthDataHolder authHolder;
     try {
-      auth = GithubUtil
-        .computeValueInModal(project, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, GithubAuthData, IOException>() {
+      authHolder = GithubUtil
+        .computeValueInModal(project, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, GithubAuthDataHolder, IOException>() {
           @NotNull
           @Override
-          public GithubAuthData convert(ProgressIndicator indicator) throws IOException {
-            return GithubUtil.getValidAuthDataFromConfig(project, indicator);
+          public GithubAuthDataHolder convert(ProgressIndicator indicator) throws IOException {
+            return GithubUtil.getValidAuthDataHolderFromConfig(project, indicator);
           }
         });
     }
@@ -153,7 +150,7 @@
       return null;
     }
 
-    return new GithubCreatePullRequestWorker(project, git, gitRepository, path, remoteName, remoteUrl, currentBranch.getName(), auth);
+    return new GithubCreatePullRequestWorker(project, git, gitRepository, path, remoteName, remoteUrl, currentBranch.getName(), authHolder);
   }
 
   @Nullable
@@ -168,7 +165,7 @@
             GitRemote targetRemote = GithubUtil.findGithubRemote(myGitRepository, forkPath);
             String targetRemoteName = targetRemote == null ? null : targetRemote.getName();
             if (targetRemoteName == null) {
-              final AtomicReference<Integer> responseRef = new AtomicReference<Integer>();
+              final Ref<Integer> responseRef = new Ref<Integer>();
               ApplicationManager.getApplication().invokeAndWait(new Runnable() {
                 @Override
                 public void run() {
@@ -182,13 +179,21 @@
             }
 
             // load available branches
-            List<String> branches = ContainerUtil.map(GithubApiUtil.getRepoBranches(myAuth, forkPath.getUser(), forkPath.getRepository()),
-                                                      new Function<GithubBranch, String>() {
-                                                        @Override
-                                                        public String fun(GithubBranch githubBranch) {
-                                                          return githubBranch.getName();
-                                                        }
-                                                      });
+            List<String> branches = ContainerUtil.map(GithubUtil.runTask(myProject, myAuthHolder, indicator,
+                                                                         new ThrowableConvertor<GithubAuthData, List<GithubBranch>, IOException>() {
+                                                                           @Override
+                                                                           public List<GithubBranch> convert(@NotNull GithubAuthData auth)
+                                                                             throws IOException {
+                                                                             return GithubApiUtil.getRepoBranches(auth, forkPath.getUser(),
+                                                                                                                  forkPath.getRepository());
+                                                                           }
+                                                                         }
+            ), new Function<GithubBranch, String>() {
+              @Override
+              public String fun(GithubBranch githubBranch) {
+                return githubBranch.getName();
+              }
+            });
 
             // fetch
             if (targetRemoteName != null) {
@@ -251,7 +256,7 @@
 
   @Nullable
   public GithubFullPath showTargetDialog(boolean firstTime) {
-    final GithubInfo2 info = getAvailableForksInModal(myProject, myGitRepository, myAuth, myPath);
+    final GithubInfo2 info = getAvailableForksInModal(myProject, myGitRepository, myAuthHolder, myPath);
     if (info == null) {
       return null;
     }
@@ -281,8 +286,8 @@
         return GithubUtil.computeValueInModal(myProject, "Access to GitHub", new Convertor<ProgressIndicator, GithubFullPath>() {
           @Nullable
           @Override
-          public GithubFullPath convert(ProgressIndicator o) {
-            return findRepositoryByUser(myProject, user, info.getForks(), myAuth, info.getSource());
+          public GithubFullPath convert(ProgressIndicator indicator) {
+            return findRepositoryByUser(myProject, myAuthHolder, indicator, user, info.getForks(), info.getSource());
           }
         });
       }
@@ -301,8 +306,11 @@
       return true;
     }
     if (info.getInfo().getBranchToHeadCommits(myGitRepository).isEmpty()) {
-      GithubNotifications.showWarningDialog(myProject, CANNOT_CREATE_PULL_REQUEST,
-        "Can't create empty pull request: the branch" + getCurrentBranch() + " in fully merged to the branch " + targetBranch + ".");
+      GithubNotifications.showWarningDialog(myProject, CANNOT_CREATE_PULL_REQUEST, "Can't create empty pull request: the branch" +
+                                                                                   getCurrentBranch() +
+                                                                                   " in fully merged to the branch " +
+                                                                                   targetBranch +
+                                                                                   ".");
       return false;
     }
     if (info.getInfo().getHeadToBranchCommits(myGitRepository).isEmpty()) {
@@ -332,7 +340,8 @@
 
         LOG.info("Creating pull request");
         indicator.setText("Creating pull request...");
-        GithubPullRequest request = createPullRequest(project, myAuth, myForkPath, title, description, headBranch, targetBranch);
+        GithubPullRequest request =
+          createPullRequest(project, myAuthHolder, indicator, myForkPath, title, description, headBranch, targetBranch);
         if (request == null) {
           return;
         }
@@ -357,14 +366,21 @@
 
   @Nullable
   private static GithubPullRequest createPullRequest(@NotNull Project project,
-                                                     @NotNull GithubAuthData auth,
-                                                     @NotNull GithubFullPath targetRepo,
-                                                     @NotNull String title,
-                                                     @NotNull String description,
-                                                     @NotNull String head,
-                                                     @NotNull String base) {
+                                                     @NotNull GithubAuthDataHolder authHolder,
+                                                     @NotNull ProgressIndicator indicator,
+                                                     @NotNull final GithubFullPath targetRepo,
+                                                     @NotNull final String title,
+                                                     @NotNull final String description,
+                                                     @NotNull final String head,
+                                                     @NotNull final String base) {
     try {
-      return GithubApiUtil.createPullRequest(auth, targetRepo.getUser(), targetRepo.getRepository(), title, description, head, base);
+      return GithubUtil.runTask(project, authHolder, indicator, new ThrowableConvertor<GithubAuthData, GithubPullRequest, IOException>() {
+        @NotNull
+        @Override
+        public GithubPullRequest convert(@NotNull GithubAuthData auth) throws IOException {
+          return GithubApiUtil.createPullRequest(auth, targetRepo.getUser(), targetRepo.getRepository(), title, description, head, base);
+        }
+      });
     }
     catch (IOException e) {
       GithubNotifications.showError(project, CANNOT_CREATE_PULL_REQUEST, e);
@@ -451,7 +467,7 @@
   @Nullable
   private static GithubInfo2 getAvailableForksInModal(@NotNull final Project project,
                                                       @NotNull final GitRepository gitRepository,
-                                                      @NotNull final GithubAuthData auth,
+                                                      @NotNull final GithubAuthDataHolder authHolder,
                                                       @NotNull final GithubFullPath path) {
     try {
       return GithubUtil
@@ -462,7 +478,15 @@
             final Set<GithubFullPath> forks = new HashSet<GithubFullPath>();
 
             // GitHub
-            GithubRepoDetailed repo = GithubApiUtil.getDetailedRepoInfo(auth, path.getUser(), path.getRepository());
+            GithubRepoDetailed repo =
+              GithubUtil.runTask(project, authHolder, indicator, new ThrowableConvertor<GithubAuthData, GithubRepoDetailed, IOException>() {
+                @NotNull
+                @Override
+                public GithubRepoDetailed convert(@NotNull GithubAuthData auth) throws IOException {
+                  return GithubApiUtil.getDetailedRepoInfo(auth, path.getUser(), path.getRepository());
+                }
+              });
+
             forks.add(path);
             if (repo.getParent() != null) {
               forks.add(repo.getParent().getFullPath());
@@ -507,10 +531,11 @@
 
   @Nullable
   private static GithubFullPath findRepositoryByUser(@NotNull Project project,
-                                                     @NotNull String user,
+                                                     @NotNull GithubAuthDataHolder authHolder,
+                                                     @NotNull ProgressIndicator indicator,
+                                                     @NotNull final String user,
                                                      @NotNull Set<GithubFullPath> forks,
-                                                     @NotNull GithubAuthData auth,
-                                                     @NotNull GithubRepo source) {
+                                                     @NotNull final GithubRepo source) {
     for (GithubFullPath path : forks) {
       if (StringUtil.equalsIgnoreCase(user, path.getUser())) {
         return path;
@@ -518,20 +543,28 @@
     }
 
     try {
-      GithubRepoDetailed target = GithubApiUtil.getDetailedRepoInfo(auth, user, source.getName());
-      if (target.getSource() != null && StringUtil.equals(target.getSource().getUserName(), source.getUserName())) {
-        return target.getFullPath();
-      }
-    }
-    catch (IOException ignore) {
-      // such repo may not exist
-    }
+      return GithubUtil.runTask(project, authHolder, indicator, new ThrowableConvertor<GithubAuthData, GithubFullPath, IOException>() {
+        @Nullable
+        @Override
+        public GithubFullPath convert(@NotNull GithubAuthData auth) throws IOException {
+          try {
+            GithubRepoDetailed target = GithubApiUtil.getDetailedRepoInfo(auth, user, source.getName());
+            if (target.getSource() != null && StringUtil.equals(target.getSource().getUserName(), source.getUserName())) {
+              return target.getFullPath();
+            }
+          }
+          catch (IOException ignore) {
+            // such repo may not exist
+          }
 
-    try {
-      GithubRepo fork = GithubApiUtil.findForkByUser(auth, source.getUserName(), source.getName(), user);
-      if (fork != null) {
-        return fork.getFullPath();
-      }
+          GithubRepo fork = GithubApiUtil.findForkByUser(auth, source.getUserName(), source.getName(), user);
+          if (fork != null) {
+            return fork.getFullPath();
+          }
+
+          return null;
+        }
+      });
     }
     catch (IOException e) {
       GithubNotifications.showError(project, CANNOT_CREATE_PULL_REQUEST, e);
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
index d3f9125..4faaf7b 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
@@ -105,7 +105,6 @@
       GithubNotifications.showError(project, CANNOT_PERFORM_GITHUB_REBASE, "Can't find git repository");
       return;
     }
-
     BasicAction.saveAll();
 
     new Task.Backgroundable(project, "Rebasing GitHub fork...") {
@@ -175,15 +174,16 @@
 
     if (GithubUtil.addGithubRemote(project, gitRepository, "upstream", parentRepoUrl)) {
       return parentRepoUrl;
-    } else {
+    }
+    else {
       return null;
     }
   }
 
   @Nullable
   private static GithubRepoDetailed loadRepositoryInfo(@NotNull Project project,
-                                                             @NotNull GitRepository gitRepository,
-                                                             @NotNull ProgressIndicator indicator) {
+                                                       @NotNull GitRepository gitRepository,
+                                                       @NotNull ProgressIndicator indicator) {
     final String remoteUrl = GithubUtil.findGithubRemoteUrl(gitRepository);
     if (remoteUrl == null) {
       GithubNotifications.showError(project, CANNOT_PERFORM_GITHUB_REBASE, "Can't find github remote");
@@ -196,13 +196,14 @@
     }
 
     try {
-      return GithubUtil.runWithValidAuth(project, indicator, new ThrowableConvertor<GithubAuthData, GithubRepoDetailed, IOException>() {
-        @Override
-        @NotNull
-        public GithubRepoDetailed convert(GithubAuthData authData) throws IOException {
-          return GithubApiUtil.getDetailedRepoInfo(authData, userAndRepo.getUser(), userAndRepo.getRepository());
-        }
-      });
+      return GithubUtil.runTask(project, GithubAuthDataHolder.createFromSettings(), indicator,
+                                new ThrowableConvertor<GithubAuthData, GithubRepoDetailed, IOException>() {
+                                  @NotNull
+                                  @Override
+                                  public GithubRepoDetailed convert(@NotNull GithubAuthData auth) throws IOException {
+                                    return GithubApiUtil.getDetailedRepoInfo(auth, userAndRepo.getUser(), userAndRepo.getRepository());
+                                  }
+                                });
     }
     catch (GithubOperationCanceledException e) {
       return null;
@@ -236,7 +237,8 @@
                                  public void run() {
                                    doRebaseCurrentBranch(project, gitRepository.getRoot(), indicator);
                                  }
-                               });
+                               }
+      );
     process.execute();
   }
 
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
index d3e72a2..99c5ff9 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
@@ -26,13 +26,13 @@
 import com.intellij.openapi.roots.FileIndexFacade;
 import com.intellij.openapi.ui.Splitter;
 import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.vcs.VcsDataKeys;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.changes.ChangeListManager;
 import com.intellij.openapi.vcs.changes.ui.SelectFilesDialog;
 import com.intellij.openapi.vcs.ui.CommitMessage;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ThrowableConsumer;
 import com.intellij.util.ThrowableConvertor;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.HashSet;
@@ -51,18 +51,18 @@
 import icons.GithubIcons;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.github.api.*;
+import org.jetbrains.plugins.github.api.GithubApiUtil;
+import org.jetbrains.plugins.github.api.GithubRepo;
+import org.jetbrains.plugins.github.api.GithubUserDetailed;
 import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
 import org.jetbrains.plugins.github.ui.GithubShareDialog;
-import org.jetbrains.plugins.github.util.GithubAuthData;
-import org.jetbrains.plugins.github.util.GithubNotifications;
-import org.jetbrains.plugins.github.util.GithubUrlUtil;
-import org.jetbrains.plugins.github.util.GithubUtil;
+import org.jetbrains.plugins.github.util.*;
 
 import javax.swing.*;
 import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 
 import static org.jetbrains.plugins.github.util.GithubUtil.setVisibleEnabled;
 
@@ -125,8 +125,10 @@
       externalRemoteDetected = !gitRepository.getRemotes().isEmpty();
     }
 
+    final GithubAuthDataHolder authHolder = GithubAuthDataHolder.createFromSettings();
+
     // get available GitHub repos with modal progress
-    final GithubInfo githubInfo = loadGithubInfoWithModal(project);
+    final GithubInfo githubInfo = loadGithubInfoWithModal(authHolder, project);
     if (githubInfo == null) {
       return;
     }
@@ -150,7 +152,7 @@
         // create GitHub repo (network)
         LOG.info("Creating GitHub repository");
         indicator.setText("Creating GitHub repository...");
-        final String url = createGithubRepository(project, githubInfo.getAuthData(), name, description, isPrivate);
+        final String url = createGithubRepository(project, authHolder, indicator, name, description, isPrivate);
         if (url == null) {
           return;
         }
@@ -202,29 +204,28 @@
   }
 
   @Nullable
-  private static GithubInfo loadGithubInfoWithModal(@NotNull final Project project) {
+  private static GithubInfo loadGithubInfoWithModal(@NotNull final GithubAuthDataHolder authHolder, @NotNull final Project project) {
     try {
       return GithubUtil
         .computeValueInModal(project, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, GithubInfo, IOException>() {
+          @NotNull
           @Override
           public GithubInfo convert(ProgressIndicator indicator) throws IOException {
             // get existing github repos (network) and validate auth data
-            final AtomicReference<List<GithubRepo>> availableReposRef = new AtomicReference<List<GithubRepo>>();
-            final GithubAuthData auth =
-              GithubUtil.runAndGetValidAuth(project, indicator, new ThrowableConsumer<GithubAuthData, IOException>() {
-                @Override
-                public void consume(GithubAuthData authData) throws IOException {
-                  availableReposRef.set(GithubApiUtil.getUserRepos(authData));
-                }
-              });
-            final HashSet<String> names = new HashSet<String>();
-            for (GithubRepo info : availableReposRef.get()) {
-              names.add(info.getName());
-            }
+            return GithubUtil.runTask(project, authHolder, indicator, new ThrowableConvertor<GithubAuthData, GithubInfo, IOException>() {
+              @NotNull
+              @Override
+              public GithubInfo convert(@NotNull GithubAuthData auth) throws IOException {
+                // check access to private repos (network)
+                GithubUserDetailed userInfo = GithubApiUtil.getCurrentUserDetailed(auth);
 
-            // check access to private repos (network)
-            final GithubUserDetailed userInfo = GithubApiUtil.getCurrentUserDetailed(auth);
-            return new GithubInfo(auth, userInfo, names);
+                HashSet<String> names = new HashSet<String>();
+                for (GithubRepo info : GithubApiUtil.getUserRepos(auth)) {
+                  names.add(info.getName());
+                }
+                return new GithubInfo(userInfo, names);
+              }
+            });
           }
         });
     }
@@ -239,14 +240,20 @@
 
   @Nullable
   private static String createGithubRepository(@NotNull Project project,
-                                               @NotNull GithubAuthData auth,
-                                               @NotNull String name,
-                                               @NotNull String description,
-                                               boolean isPrivate) {
+                                               @NotNull GithubAuthDataHolder authHolder,
+                                               @NotNull ProgressIndicator indicator,
+                                               @NotNull final String name,
+                                               @NotNull final String description,
+                                               final boolean isPrivate) {
 
     try {
-      GithubRepo response = GithubApiUtil.createRepo(auth, name, description, isPrivate);
-      return response.getHtmlUrl();
+      return GithubUtil.runTask(project, authHolder, indicator, new ThrowableConvertor<GithubAuthData, GithubRepo, IOException>() {
+        @NotNull
+        @Override
+        public GithubRepo convert(@NotNull GithubAuthData auth) throws IOException {
+          return GithubApiUtil.createRepo(auth, name, description, isPrivate);
+        }
+      }).getHtmlUrl();
     }
     catch (IOException e) {
       GithubNotifications.showError(project, "Failed to create GitHub Repository", e);
@@ -286,15 +293,15 @@
 
       // ask for files to add
       final List<VirtualFile> trackedFiles = ChangeListManager.getInstance(project).getAffectedFiles();
-      final Collection<VirtualFile> untrackedFiles = filterOutIgnored(project,
-                                                                      repository.getUntrackedFilesHolder().retrieveUntrackedFiles());
+      final Collection<VirtualFile> untrackedFiles =
+        filterOutIgnored(project, repository.getUntrackedFilesHolder().retrieveUntrackedFiles());
       trackedFiles.removeAll(untrackedFiles); // fix IDEA-119855
 
       final List<VirtualFile> allFiles = new ArrayList<VirtualFile>();
       allFiles.addAll(trackedFiles);
       allFiles.addAll(untrackedFiles);
 
-      final AtomicReference<GithubUntrackedFilesDialog> dialogRef = new AtomicReference<GithubUntrackedFilesDialog>();
+      final Ref<GithubUntrackedFilesDialog> dialogRef = new Ref<GithubUntrackedFilesDialog>();
       ApplicationManager.getApplication().invokeAndWait(new Runnable() {
         @Override
         public void run() {
@@ -429,12 +436,10 @@
 
   private static class GithubInfo {
     @NotNull private final GithubUserDetailed myUser;
-    @NotNull private final GithubAuthData myAuthData;
     @NotNull private final HashSet<String> myRepositoryNames;
 
-    GithubInfo(@NotNull GithubAuthData auth, @NotNull GithubUserDetailed user, @NotNull HashSet<String> repositoryNames) {
+    GithubInfo(@NotNull GithubUserDetailed user, @NotNull HashSet<String> repositoryNames) {
       myUser = user;
-      myAuthData = auth;
       myRepositoryNames = repositoryNames;
     }
 
@@ -444,11 +449,6 @@
     }
 
     @NotNull
-    public GithubAuthData getAuthData() {
-      return myAuthData;
-    }
-
-    @NotNull
     public HashSet<String> getRepositoryNames() {
       return myRepositoryNames;
     }
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
index ec7d3ae..581dc16 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
@@ -169,6 +169,10 @@
     if (tokenAuth != null) {
       method.addRequestHeader("Authorization", "token " + tokenAuth.getToken());
     }
+    GithubAuthData.BasicAuth basicAuth = auth.getBasicAuth();
+    if (basicAuth != null && basicAuth.getCode() != null) {
+      method.addRequestHeader("X-GitHub-OTP", basicAuth.getCode());
+    }
     for (Header header : headers) {
       method.addRequestHeader(header);
     }
@@ -401,6 +405,14 @@
    * Github API
    */
 
+  public static void askForTwoFactorCodeSMS(@NotNull GithubAuthData auth) {
+    try {
+      postRequest(auth, "/authorizations", null, ACCEPT_V3_JSON);
+    } catch (IOException e) {
+      LOG.info(e);
+    }
+  }
+
   @NotNull
   public static Collection<String> getTokenScopes(@NotNull GithubAuthData auth) throws IOException {
     HttpMethod method = null;
@@ -448,10 +460,9 @@
 
   @NotNull
   public static String getMasterToken(@NotNull GithubAuthData auth, @Nullable String note) throws IOException {
-    List<String> scopes = new ArrayList<String>();
-
-    scopes.add("repo"); // read/write access to public/private repositories
-    scopes.add("gist"); // create/delete gists
+    // "repo" - read/write access to public/private repositories
+    // "gist" - create/delete gists
+    List<String> scopes = Arrays.asList("repo", "gist");
 
     return getScopedToken(auth, scopes, note);
   }
diff --git a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
index 6689138..ee117b0 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
@@ -32,6 +32,7 @@
 import org.jetbrains.plugins.github.api.GithubRepo;
 import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
 import org.jetbrains.plugins.github.util.GithubAuthData;
+import org.jetbrains.plugins.github.util.GithubAuthDataHolder;
 import org.jetbrains.plugins.github.util.GithubNotifications;
 import org.jetbrains.plugins.github.util.GithubUtil;
 
@@ -60,12 +61,15 @@
           @NotNull
           @Override
           public List<GithubRepo> convert(ProgressIndicator indicator) throws IOException {
-            return GithubUtil.runWithValidAuth(project, indicator, new ThrowableConvertor<GithubAuthData, List<GithubRepo>, IOException>() {
-              @Override
-              public List<GithubRepo> convert(GithubAuthData authData) throws IOException {
-                return GithubApiUtil.getAvailableRepos(authData);
-              }
-            });
+            return GithubUtil.runTask(project, GithubAuthDataHolder.createFromSettings(), indicator,
+                                      new ThrowableConvertor<GithubAuthData, List<GithubRepo>, IOException>() {
+                                        @NotNull
+                                        @Override
+                                        public List<GithubRepo> convert(@NotNull GithubAuthData auth) throws IOException {
+                                          return GithubApiUtil.getAvailableRepos(auth);
+                                        }
+                                      }
+            );
           }
         });
     }
diff --git a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java
index 568a010..a340de0 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java
@@ -37,6 +37,9 @@
     }
 
     GithubSettings settings = GithubSettings.getInstance();
+    if (!settings.isValidGitAuth()) {
+      return null;
+    }
 
     String host1 = GithubUrlUtil.getHostFromUrl(settings.getHost());
     String host2 = GithubUrlUtil.getHostFromUrl(url);
diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
index 8af4136..059be25 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
@@ -13,11 +13,12 @@
 import com.intellij.util.ui.GridBag;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.github.api.GithubApiUtil;
 import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
 import org.jetbrains.plugins.github.util.GithubAuthData;
+import org.jetbrains.plugins.github.util.GithubAuthDataHolder;
 import org.jetbrains.plugins.github.util.GithubNotifications;
 import org.jetbrains.plugins.github.util.GithubUtil;
-import org.jetbrains.plugins.github.api.GithubApiUtil;
 
 import javax.swing.*;
 import javax.swing.event.DocumentEvent;
@@ -124,15 +125,19 @@
           @Override
           public String convert(ProgressIndicator indicator) throws IOException {
             return GithubUtil
-              .runWithValidBasicAuthForHost(myProject, indicator, getHost(), new ThrowableConvertor<GithubAuthData, String, IOException>() {
-                @NotNull
-                @Override
-                public String convert(GithubAuthData auth) throws IOException {
-                  return GithubApiUtil.getReadOnlyToken(auth, getRepoAuthor(), getRepoName(), "Intellij tasks plugin");
-                }
-              });
+              .runTaskWithBasicAuthForHost(myProject, GithubAuthDataHolder.createFromSettings(), indicator, getHost(),
+                                           new ThrowableConvertor<GithubAuthData, String, IOException>() {
+                                             @NotNull
+                                             @Override
+                                             public String convert(@NotNull GithubAuthData auth) throws IOException {
+                                               return GithubApiUtil
+                                                 .getReadOnlyToken(auth, getRepoAuthor(), getRepoName(), "Intellij tasks plugin");
+                                             }
+                                           }
+              );
           }
-        }));
+        })
+      );
     }
     catch (GithubOperationCanceledException ignore) {
     }
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubBasicLoginDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubBasicLoginDialog.java
index fac45c5..80acc78 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubBasicLoginDialog.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubBasicLoginDialog.java
@@ -16,25 +16,17 @@
 package org.jetbrains.plugins.github.ui;
 
 import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.plugins.github.util.GithubAuthData;
-import org.jetbrains.plugins.github.util.GithubSettings;
 
 /**
  * @author Aleksey Pivovarov
  */
 public class GithubBasicLoginDialog extends GithubLoginDialog {
 
-  public GithubBasicLoginDialog(@Nullable Project project) {
-    super(project);
+  public GithubBasicLoginDialog(@NotNull Project project, @NotNull GithubAuthData oldAuthData, @NotNull String host) {
+    super(project, oldAuthData);
     myGithubLoginPanel.lockAuthType(GithubAuthData.AuthType.BASIC);
-  }
-
-  @Override
-  protected void saveCredentials(GithubAuthData auth) {
-    final GithubSettings settings = GithubSettings.getInstance();
-    if (settings.getAuthType() != GithubAuthData.AuthType.TOKEN) {
-      settings.setCredentials(myGithubLoginPanel.getHost(), auth, myGithubLoginPanel.isSavePasswordSelected());
-    }
+    myGithubLoginPanel.lockHost(host);
   }
 }
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java
index 7660fb5..c4e33f6 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java
@@ -6,9 +6,9 @@
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.util.ThrowableConvertor;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.github.api.GithubUser;
 import org.jetbrains.plugins.github.util.GithubAuthData;
+import org.jetbrains.plugins.github.util.GithubAuthDataHolder;
 import org.jetbrains.plugins.github.util.GithubSettings;
 import org.jetbrains.plugins.github.util.GithubUtil;
 
@@ -25,18 +25,25 @@
 
   protected final GithubLoginPanel myGithubLoginPanel;
   protected final GithubSettings mySettings;
+
   protected final Project myProject;
 
-  public GithubLoginDialog(@Nullable final Project project) {
+  protected GithubAuthData myAuthData;
+
+  public GithubLoginDialog(@NotNull final Project project, @NotNull GithubAuthData oldAuthData) {
     super(project, true);
     myProject = project;
+
     myGithubLoginPanel = new GithubLoginPanel(this);
 
-    mySettings = GithubSettings.getInstance();
-    myGithubLoginPanel.setHost(mySettings.getHost());
-    myGithubLoginPanel.setLogin(mySettings.getLogin());
-    myGithubLoginPanel.setAuthType(mySettings.getAuthType());
+    myGithubLoginPanel.setHost(oldAuthData.getHost());
+    myGithubLoginPanel.setAuthType(oldAuthData.getAuthType());
+    GithubAuthData.BasicAuth basicAuth = oldAuthData.getBasicAuth();
+    if (basicAuth != null) {
+      myGithubLoginPanel.setLogin(basicAuth.getLogin());
+    }
 
+    mySettings = GithubSettings.getInstance();
     if (mySettings.isSavePasswordMakesSense()) {
       myGithubLoginPanel.setSavePasswordSelected(mySettings.isSavePassword());
     }
@@ -71,17 +78,18 @@
 
   @Override
   protected void doOKAction() {
-    final GithubAuthData auth = myGithubLoginPanel.getAuthData();
+    final GithubAuthDataHolder authHolder = new GithubAuthDataHolder(myGithubLoginPanel.getAuthData());
     try {
       GithubUtil.computeValueInModal(myProject, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, GithubUser, IOException>() {
         @NotNull
         @Override
         public GithubUser convert(ProgressIndicator indicator) throws IOException {
-          return GithubUtil.checkAuthData(auth);
+          return GithubUtil.checkAuthData(myProject, authHolder, indicator);
         }
       });
 
-      saveCredentials(auth);
+      myAuthData = authHolder.getAuthData();
+
       if (mySettings.isSavePasswordMakesSense()) {
         mySettings.setSavePassword(myGithubLoginPanel.isSavePasswordSelected());
       }
@@ -93,21 +101,19 @@
     }
   }
 
-  protected void saveCredentials(GithubAuthData auth) {
-    final GithubSettings settings = GithubSettings.getInstance();
-    settings.setCredentials(myGithubLoginPanel.getHost(), auth, myGithubLoginPanel.isSavePasswordSelected());
-  }
-
-  public void clearErrors() {
-    setErrorText(null);
+  public boolean isSavePasswordSelected() {
+    return myGithubLoginPanel.isSavePasswordSelected();
   }
 
   @NotNull
   public GithubAuthData getAuthData() {
-    return myGithubLoginPanel.getAuthData();
+    if (myAuthData == null) {
+      throw new IllegalStateException("AuthData is not set");
+    }
+    return myAuthData;
   }
 
-  public void lockHost(String host) {
-    myGithubLoginPanel.lockHost(host);
+  public void clearErrors() {
+    setErrorText(null);
   }
 }
\ No newline at end of file
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
index 9e8f9ab..80e5a6f 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
@@ -100,7 +100,7 @@
               @NotNull
               @Override
               public GithubUser convert(ProgressIndicator indicator) throws IOException {
-                return GithubUtil.checkAuthData(auth);
+                return GithubUtil.checkAuthData(project, new GithubAuthDataHolder(auth), indicator);
               }
             });
 
@@ -132,13 +132,14 @@
               @NotNull
               @Override
               public String convert(ProgressIndicator indicator) throws IOException {
-                return GithubUtil.runWithValidBasicAuthForHost(project, indicator, getHost(),
-                                                               new ThrowableConvertor<GithubAuthData, String, IOException>() {
-                                                                 @Override
-                                                                 public String convert(GithubAuthData auth) throws IOException {
-                                                                   return GithubApiUtil.getMasterToken(auth, "IntelliJ plugin");
-                                                                 }
-                                                               }
+                return GithubUtil.runTaskWithBasicAuthForHost(project, GithubAuthDataHolder.createFromSettings(), indicator, getHost(),
+                                                              new ThrowableConvertor<GithubAuthData, String, IOException>() {
+                                                                @NotNull
+                                                                @Override
+                                                                public String convert(@NotNull GithubAuthData auth) throws IOException {
+                                                                  return GithubApiUtil.getMasterToken(auth, "IntelliJ plugin");
+                                                                }
+                                                              }
                 );
               }
             })
@@ -294,7 +295,7 @@
 
   public void apply() {
     if (myCredentialsModified) {
-      mySettings.setCredentials(getHost(), getAuthData(), true);
+      mySettings.setAuthData(getAuthData(), true);
     }
     mySettings.setConnectionTimeout(getConnectionTimeout());
     resetCredentialsModification();
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
index 63e93a6..f110444 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.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.
@@ -21,10 +21,12 @@
 
 /**
  * Container for authentication data:
- * - host
- * - login
+ * * host
+ * * credentials
  *    - login/password pair
- *    or
+ *        or
+ *    - login/password pair/2 factor code
+ *        or
  *    - OAuth2 access token
  *
  * @author Aleksey Pivovarov
@@ -38,7 +40,6 @@
   @Nullable private final TokenAuth myTokenAuth;
   private final boolean myUseProxy;
 
-
   private GithubAuthData(@NotNull AuthType authType,
                          @NotNull String host,
                          @Nullable BasicAuth basicAuth,
@@ -51,6 +52,10 @@
     myUseProxy = useProxy;
   }
 
+  public static GithubAuthData createFromSettings() {
+    return GithubSettings.getInstance().getAuthData();
+  }
+
   public static GithubAuthData createAnonymous() {
     return createAnonymous(GithubApiUtil.DEFAULT_GITHUB_HOST);
   }
@@ -63,6 +68,13 @@
     return new GithubAuthData(AuthType.BASIC, host, new BasicAuth(login, password), null, true);
   }
 
+  public static GithubAuthData createBasicAuthTF(@NotNull String host,
+                                                 @NotNull String login,
+                                                 @NotNull String password,
+                                                 @NotNull String code) {
+    return new GithubAuthData(AuthType.BASIC, host, new BasicAuth(login, password, code), null, true);
+  }
+
   public static GithubAuthData createTokenAuth(@NotNull String host, @NotNull String token) {
     return new GithubAuthData(AuthType.TOKEN, host, null, new TokenAuth(token), true);
   }
@@ -95,13 +107,28 @@
     return myUseProxy;
   }
 
+  @NotNull
+  public GithubAuthData copyWithTwoFactorCode(@NotNull String code) {
+    if (myBasicAuth == null) {
+      throw new IllegalStateException("Two factor authentication can be used only with Login/Password");
+    }
+
+    return createBasicAuthTF(getHost(), myBasicAuth.getLogin(), myBasicAuth.getPassword(), code);
+  }
+
   public static class BasicAuth {
     @NotNull private final String myLogin;
     @NotNull private final String myPassword;
+    @Nullable private final String myCode;
 
     private BasicAuth(@NotNull String login, @NotNull String password) {
+      this(login, password, null);
+    }
+
+    private BasicAuth(@NotNull String login, @NotNull String password, @Nullable String code) {
       myLogin = login;
       myPassword = password;
+      myCode = code;
     }
 
     @NotNull
@@ -113,6 +140,11 @@
     public String getPassword() {
       return myPassword;
     }
+
+    @Nullable
+    public String getCode() {
+      return myCode;
+    }
   }
 
   public static class TokenAuth {
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java
new file mode 100644
index 0000000..695dfe7
--- /dev/null
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java
@@ -0,0 +1,46 @@
+/*
+ * 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 org.jetbrains.plugins.github.util;
+
+import com.intellij.openapi.util.ThrowableComputable;
+import org.jetbrains.annotations.NotNull;
+
+
+public class GithubAuthDataHolder {
+  @NotNull private GithubAuthData myAuthData;
+
+  public GithubAuthDataHolder(@NotNull GithubAuthData auth) {
+    myAuthData = auth;
+  }
+
+  @NotNull
+  public synchronized GithubAuthData getAuthData() {
+    return myAuthData;
+  }
+
+  public synchronized <T extends Throwable> void runTransaction(@NotNull GithubAuthData expected,
+                                                                @NotNull ThrowableComputable<GithubAuthData, T> task) throws T {
+    if (expected != myAuthData) {
+      return;
+    }
+
+    myAuthData = task.compute();
+  }
+
+  public static GithubAuthDataHolder createFromSettings() {
+    return new GithubAuthDataHolder(GithubSettings.getInstance().getAuthData());
+  }
+}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
index 49199c0..3523e41 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
@@ -59,6 +59,7 @@
     public boolean PRIVATE_GIST = true;
     public boolean SAVE_PASSWORD = true;
     public int CONNECTION_TIMEOUT = 5000;
+    public boolean VALID_GIT_AUTH = true;
   }
 
   public static GithubSettings getInstance() {
@@ -120,6 +121,10 @@
     return myState.SAVE_PASSWORD;
   }
 
+  public boolean isValidGitAuth() {
+    return myState.VALID_GIT_AUTH;
+  }
+
   public boolean isSavePasswordMakesSense() {
     final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
     return passwordSafe.getSettings().getProviderType() == PasswordSafeSettings.ProviderType.MASTER_PASSWORD;
@@ -137,6 +142,10 @@
     myState.SAVE_PASSWORD = savePassword;
   }
 
+  public void setValidGitAuth(final boolean validGitAuth) {
+    myState.VALID_GIT_AUTH = validGitAuth;
+  }
+
   public void setOpenInBrowserGist(final boolean openInBrowserGist) {
     myState.OPEN_IN_BROWSER_GIST = openInBrowserGist;
   }
@@ -172,10 +181,25 @@
     }
   }
 
+  private static boolean isValidGitAuth(@NotNull GithubAuthData auth) {
+    switch (auth.getAuthType()) {
+      case BASIC:
+        assert auth.getBasicAuth() != null;
+        return auth.getBasicAuth().getCode() == null;
+      case TOKEN:
+        return true;
+      case ANONYMOUS:
+        return false;
+      default:
+        throw new IllegalStateException("GithubSettings: setAuthData - wrong AuthType: " + auth.getAuthType());
+    }
+  }
+
   @NotNull
   public GithubAuthData getAuthData() {
     switch (getAuthType()) {
       case BASIC:
+        //noinspection ConstantConditions
         return GithubAuthData.createBasicAuth(getHost(), getLogin(), getPassword());
       case TOKEN:
         return GithubAuthData.createTokenAuth(getHost(), getPassword());
@@ -186,8 +210,11 @@
     }
   }
 
-  private void setAuthData(@NotNull GithubAuthData auth, boolean rememberPassword) {
+  public void setAuthData(@NotNull GithubAuthData auth, boolean rememberPassword) {
+    setValidGitAuth(isValidGitAuth(auth));
+
     setAuthType(auth.getAuthType());
+    setHost(auth.getHost());
 
     switch (auth.getAuthType()) {
       case BASIC:
@@ -205,12 +232,7 @@
         setPassword("", rememberPassword);
         break;
       default:
-        throw new IllegalStateException("GithubSettings: setAuthData - wrong AuthType: " + getAuthType());
+        throw new IllegalStateException("GithubSettings: setAuthData - wrong AuthType: " + auth.getAuthType());
     }
   }
-
-  public void setCredentials(@NotNull String host, @NotNull GithubAuthData auth, boolean rememberPassword) {
-    setHost(host);
-    setAuthData(auth, rememberPassword);
-  }
 }
\ No newline at end of file
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUrlUtil.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUrlUtil.java
index a79a2f4..d65b5d7 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUrlUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUrlUtil.java
@@ -126,6 +126,7 @@
   }
 
   public static boolean isGithubUrl(@NotNull String url, @NotNull String host) {
+    host = getHostFromUrl(host);
     url = removeProtocolPrefix(url);
     if (StringUtil.startsWithIgnoreCase(url, host)) {
       if (url.length() > host.length() && ":/".indexOf(url.charAt(host.length())) == -1) {
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
index a3eb6c4..db13788 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
@@ -22,7 +22,10 @@
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.ThrowableComputable;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -46,13 +49,13 @@
 import org.jetbrains.plugins.github.api.GithubUserDetailed;
 import org.jetbrains.plugins.github.exceptions.GithubAuthenticationException;
 import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
+import org.jetbrains.plugins.github.exceptions.GithubTwoFactorAuthenticationException;
 import org.jetbrains.plugins.github.ui.GithubBasicLoginDialog;
 import org.jetbrains.plugins.github.ui.GithubLoginDialog;
 
 import java.io.IOException;
 import java.net.UnknownHostException;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Various utility methods for the GutHub plugin.
@@ -65,119 +68,194 @@
 
   public static final Logger LOG = Logger.getInstance("github");
 
-  // TODO: these functions ugly inside and out
+  // TODO: Consider sharing of GithubAuthData between actions (as member of GithubSettings)
   @NotNull
-  public static GithubAuthData runAndGetValidAuth(@Nullable Project project,
+  public static <T> T runTask(@NotNull Project project,
+                              @NotNull GithubAuthDataHolder authHolder,
+                              @NotNull ProgressIndicator indicator,
+                              @NotNull ThrowableConvertor<GithubAuthData, T, IOException> task) throws IOException {
+    GithubAuthData auth = authHolder.getAuthData();
+    try {
+      return task.convert(auth);
+    }
+    catch (GithubTwoFactorAuthenticationException e) {
+      getTwoFactorAuthData(project, authHolder, indicator, auth);
+      return runTask(project, authHolder, indicator, task);
+    }
+    catch (GithubAuthenticationException e) {
+      getValidAuthData(project, authHolder, indicator, auth);
+      return runTask(project, authHolder, indicator, task);
+    }
+  }
+
+  public static void runTask(@NotNull Project project,
+                             @NotNull GithubAuthDataHolder authHolder,
+                             @NotNull ProgressIndicator indicator,
+                             @NotNull ThrowableConsumer<GithubAuthData, IOException> task) throws IOException {
+    GithubAuthData auth = authHolder.getAuthData();
+    try {
+      task.consume(auth);
+    }
+    catch (GithubTwoFactorAuthenticationException e) {
+      getTwoFactorAuthData(project, authHolder, indicator, auth);
+      runTask(project, authHolder, indicator, task);
+    }
+    catch (GithubAuthenticationException e) {
+      getValidAuthData(project, authHolder, indicator, auth);
+      runTask(project, authHolder, indicator, task);
+    }
+  }
+
+  @NotNull
+  public static <T> T runTaskWithBasicAuthForHost(@NotNull Project project,
+                                                  @NotNull GithubAuthDataHolder authHolder,
                                                   @NotNull ProgressIndicator indicator,
-                                                  @NotNull ThrowableConsumer<GithubAuthData, IOException> task) throws IOException {
-    GithubAuthData auth = GithubSettings.getInstance().getAuthData();
+                                                  @NotNull String host,
+                                                  @NotNull ThrowableConvertor<GithubAuthData, T, IOException> task) throws IOException {
+    GithubAuthData auth = authHolder.getAuthData();
     try {
-      if (auth.getAuthType() == GithubAuthData.AuthType.ANONYMOUS) {
-        throw new GithubAuthenticationException("Bad authentication type");
+      if (auth.getAuthType() != GithubAuthData.AuthType.BASIC) {
+        throw new GithubAuthenticationException("Expected basic authentication");
       }
-      task.consume(auth);
-      return auth;
+      return task.convert(auth);
+    }
+    catch (GithubTwoFactorAuthenticationException e) {
+      getTwoFactorAuthData(project, authHolder, indicator, auth);
+      return runTaskWithBasicAuthForHost(project, authHolder, indicator, host, task);
     }
     catch (GithubAuthenticationException e) {
-      auth = getValidAuthData(project, indicator);
-      task.consume(auth);
-      return auth;
+      getValidBasicAuthDataForHost(project, authHolder, indicator, auth, host);
+      return runTaskWithBasicAuthForHost(project, authHolder, indicator, host, task);
     }
   }
 
   @NotNull
-  public static <T> T runWithValidAuth(@Nullable Project project,
-                                       @NotNull ProgressIndicator indicator,
-                                       @NotNull ThrowableConvertor<GithubAuthData, T, IOException> task) throws IOException {
-    GithubAuthData auth = GithubSettings.getInstance().getAuthData();
+  private static GithubUserDetailed testConnection(@NotNull Project project,
+                                                   @NotNull GithubAuthDataHolder authHolder,
+                                                   @NotNull ProgressIndicator indicator) throws IOException {
+    GithubAuthData auth = authHolder.getAuthData();
     try {
-      if (auth.getAuthType() == GithubAuthData.AuthType.ANONYMOUS) {
-        throw new GithubAuthenticationException("Bad authentication type");
-      }
-      return task.convert(auth);
+      return GithubApiUtil.getCurrentUserDetailed(auth);
     }
-    catch (GithubAuthenticationException e) {
-      auth = getValidAuthData(project, indicator);
-      return task.convert(auth);
+    catch (GithubTwoFactorAuthenticationException e) {
+      getTwoFactorAuthData(project, authHolder, indicator, auth);
+      return testConnection(project, authHolder, indicator);
     }
   }
 
-  @NotNull
-  public static <T> T runWithValidBasicAuthForHost(@Nullable Project project,
-                                                   @NotNull ProgressIndicator indicator,
-                                                   @NotNull String host,
-                                                   @NotNull ThrowableConvertor<GithubAuthData, T, IOException> task) throws IOException {
-    GithubSettings settings = GithubSettings.getInstance();
-    GithubAuthData auth = null;
-    try {
-      if (settings.getAuthType() != GithubAuthData.AuthType.BASIC ||
-          !StringUtil.equalsIgnoreCase(GithubUrlUtil.getApiUrl(host), GithubUrlUtil.getApiUrl(settings.getHost()))) {
-        throw new GithubAuthenticationException("Bad authentication type");
-      }
-      auth = settings.getAuthData();
-      return task.convert(auth);
-    }
-    catch (GithubAuthenticationException e) {
-      auth = getValidBasicAuthDataForHost(project, indicator, host);
-      return task.convert(auth);
-    }
-  }
-
-  /**
-   * @return null if user canceled login dialog. Valid GithubAuthData otherwise.
-   */
-  @NotNull
-  public static GithubAuthData getValidAuthData(@Nullable Project project, @NotNull ProgressIndicator indicator)
-    throws GithubOperationCanceledException {
-    final GithubLoginDialog dialog = new GithubLoginDialog(project);
-    ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+  public static void getValidAuthData(@NotNull final Project project,
+                                      @NotNull final GithubAuthDataHolder authHolder,
+                                      @NotNull final ProgressIndicator indicator,
+                                      @NotNull final GithubAuthData oldAuth) throws GithubOperationCanceledException {
+    authHolder.runTransaction(oldAuth, new ThrowableComputable<GithubAuthData, GithubOperationCanceledException>() {
       @Override
-      public void run() {
-        DialogManager.show(dialog);
+      @NotNull
+      public GithubAuthData compute() throws GithubOperationCanceledException {
+        final GithubLoginDialog dialog = new GithubLoginDialog(project, oldAuth);
+        ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+          @Override
+          public void run() {
+            DialogManager.show(dialog);
+          }
+        }, indicator.getModalityState());
+        if (!dialog.isOK()) {
+          throw new GithubOperationCanceledException("Can't get valid credentials");
+        }
+        GithubAuthData authData = dialog.getAuthData();
+
+        GithubSettings.getInstance().setAuthData(authData, dialog.isSavePasswordSelected());
+        return authData;
       }
-    }, indicator.getModalityState());
-    if (!dialog.isOK()) {
-      throw new GithubOperationCanceledException("Can't get valid credentials");
-    }
-    return dialog.getAuthData();
+    });
   }
 
-  /**
-   * @return null if user canceled login dialog. Valid GithubAuthData otherwise.
-   */
-  @NotNull
-  public static GithubAuthData getValidBasicAuthDataForHost(@Nullable Project project,
-                                                            @NotNull ProgressIndicator indicator,
-                                                            @NotNull String host) throws GithubOperationCanceledException {
-    final GithubLoginDialog dialog = new GithubBasicLoginDialog(project);
-    dialog.lockHost(host);
-    ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+  public static void getValidBasicAuthDataForHost(@NotNull final Project project,
+                                                  @NotNull final GithubAuthDataHolder authHolder,
+                                                  @NotNull final ProgressIndicator indicator,
+                                                  @NotNull final GithubAuthData oldAuth,
+                                                  @NotNull final String host) throws GithubOperationCanceledException {
+    authHolder.runTransaction(oldAuth, new ThrowableComputable<GithubAuthData, GithubOperationCanceledException>() {
       @Override
-      public void run() {
-        DialogManager.show(dialog);
+      @NotNull
+      public GithubAuthData compute() throws GithubOperationCanceledException {
+        final GithubLoginDialog dialog = new GithubBasicLoginDialog(project, oldAuth, host);
+        ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+          @Override
+          public void run() {
+            DialogManager.show(dialog);
+          }
+        }, indicator.getModalityState());
+        if (!dialog.isOK()) {
+          throw new GithubOperationCanceledException("Can't get valid credentials");
+        }
+        GithubAuthData authData = dialog.getAuthData();
+
+        final GithubSettings settings = GithubSettings.getInstance();
+        if (settings.getAuthType() != GithubAuthData.AuthType.TOKEN) {
+          GithubSettings.getInstance().setAuthData(authData, dialog.isSavePasswordSelected());
+        }
+        return authData;
       }
-    }, indicator.getModalityState());
-    if (!dialog.isOK()) {
-      throw new GithubOperationCanceledException("Can't get valid credentials");
-    }
-    return dialog.getAuthData();
+    });
+  }
+
+  private static void getTwoFactorAuthData(@NotNull final Project project,
+                                           @NotNull final GithubAuthDataHolder authHolder,
+                                           @NotNull final ProgressIndicator indicator,
+                                           @NotNull final GithubAuthData oldAuth) throws GithubOperationCanceledException {
+    authHolder.runTransaction(oldAuth, new ThrowableComputable<GithubAuthData, GithubOperationCanceledException>() {
+      @Override
+      @NotNull
+      public GithubAuthData compute() throws GithubOperationCanceledException {
+        if (authHolder.getAuthData().getAuthType() != GithubAuthData.AuthType.BASIC) {
+          throw new GithubOperationCanceledException("Two factor authentication can be used only with Login/Password");
+        }
+
+        GithubApiUtil.askForTwoFactorCodeSMS(oldAuth);
+
+        final Ref<String> codeRef = new Ref<String>();
+        ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+          @Override
+          public void run() {
+            codeRef.set(Messages.showInputDialog(project, "Authentication Code", "Github Two-Factor Authentication", null));
+          }
+        }, indicator.getModalityState());
+        if (codeRef.isNull()) {
+          throw new GithubOperationCanceledException("Can't get two factor authentication code");
+        }
+
+        GithubSettings settings = GithubSettings.getInstance();
+        if (settings.getAuthType() == GithubAuthData.AuthType.BASIC &&
+            StringUtil.equalsIgnoreCase(settings.getLogin(), oldAuth.getBasicAuth().getLogin())) {
+          settings.setValidGitAuth(false);
+        }
+
+        return oldAuth.copyWithTwoFactorCode(codeRef.get());
+      }
+    });
   }
 
   @NotNull
-  public static GithubAuthData getValidAuthDataFromConfig(@Nullable Project project, @NotNull ProgressIndicator indicator)
+  public static GithubAuthDataHolder getValidAuthDataHolderFromConfig(@NotNull Project project, @NotNull ProgressIndicator indicator)
     throws IOException {
-    GithubAuthData auth = GithubSettings.getInstance().getAuthData();
+    GithubAuthData auth = GithubAuthData.createFromSettings();
+    GithubAuthDataHolder authHolder = new GithubAuthDataHolder(auth);
     try {
-      checkAuthData(auth);
-      return auth;
+      checkAuthData(project, authHolder, indicator);
+      return authHolder;
     }
     catch (GithubAuthenticationException e) {
-      return getValidAuthData(project, indicator);
+      getValidAuthData(project, authHolder, indicator, auth);
+      return authHolder;
     }
   }
 
   @NotNull
-  public static GithubUserDetailed checkAuthData(@NotNull GithubAuthData auth) throws IOException {
+  public static GithubUserDetailed checkAuthData(@NotNull Project project,
+                                                 @NotNull GithubAuthDataHolder authHolder,
+                                                 @NotNull ProgressIndicator indicator) throws IOException {
+    GithubAuthData auth = authHolder.getAuthData();
+
     if (StringUtil.isEmptyOrSpaces(auth.getHost())) {
       throw new GithubAuthenticationException("Target host not defined");
     }
@@ -201,37 +279,31 @@
         throw new GithubAuthenticationException("Anonymous connection not allowed");
     }
 
-    return testConnection(auth);
+    return testConnection(project, authHolder, indicator);
   }
 
-  @NotNull
-  private static GithubUserDetailed testConnection(@NotNull GithubAuthData auth) throws IOException {
-    return GithubApiUtil.getCurrentUserDetailed(auth);
-  }
-
-  public static <T, E extends Throwable> T computeValueInModal(@NotNull Project project,
-                                                               @NotNull String caption,
-                                                               @NotNull final ThrowableConvertor<ProgressIndicator, T, E> task) throws E {
-    final AtomicReference<T> dataRef = new AtomicReference<T>();
-    final AtomicReference<E> exceptionRef = new AtomicReference<E>();
+  public static <T> T computeValueInModal(@NotNull Project project,
+                                          @NotNull String caption,
+                                          @NotNull final ThrowableConvertor<ProgressIndicator, T, IOException> task) throws IOException {
+    final Ref<T> dataRef = new Ref<T>();
+    final Ref<IOException> exceptionRef = new Ref<IOException>();
     ProgressManager.getInstance().run(new Task.Modal(project, caption, true) {
       public void run(@NotNull ProgressIndicator indicator) {
         try {
           dataRef.set(task.convert(indicator));
         }
+        catch (IOException e) {
+          exceptionRef.set(e);
+        }
         catch (Error e) {
-          throw e;
+          exceptionRef.set(new GithubOperationCanceledException(e));
         }
         catch (RuntimeException e) {
-          throw e;
-        }
-        catch (Throwable e) {
-          //noinspection unchecked
-          exceptionRef.set((E)e);
+          exceptionRef.set(new GithubOperationCanceledException(e));
         }
       }
     });
-    if (exceptionRef.get() != null) {
+    if (!exceptionRef.isNull()) {
       throw exceptionRef.get();
     }
     return dataRef.get();
@@ -240,7 +312,7 @@
   public static <T> T computeValueInModal(@NotNull Project project,
                                           @NotNull String caption,
                                           @NotNull final Convertor<ProgressIndicator, T> task) {
-    final AtomicReference<T> dataRef = new AtomicReference<T>();
+    final Ref<T> dataRef = new Ref<T>();
     ProgressManager.getInstance().run(new Task.Modal(project, caption, true) {
       public void run(@NotNull ProgressIndicator indicator) {
         dataRef.set(task.convert(indicator));
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTest.java
index 0d394d5..f7ae343 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTest.java
@@ -15,8 +15,11 @@
  */
 package org.jetbrains.plugins.github;
 
+import com.intellij.mock.MockProgressIndicator;
 import com.intellij.notification.NotificationType;
+import com.intellij.openapi.progress.ProgressIndicator;
 import org.jetbrains.plugins.github.util.GithubAuthData;
+import org.jetbrains.plugins.github.util.GithubAuthDataHolder;
 
 import java.util.Collections;
 import java.util.List;
@@ -27,10 +30,12 @@
  * @author Aleksey Pivovarov
  */
 public class GithubCreateGistTest extends GithubCreateGistTestBase {
+  private final ProgressIndicator myIndicator = new MockProgressIndicator();
+
   public void testSimple() throws Throwable {
     List<FileContent> expected = createContent();
 
-    String url = GithubCreateGistAction.createGist(myProject, myGitHubSettings.getAuthData(), expected, true, GIST_DESCRIPTION, null);
+    String url = GithubCreateGistAction.createGist(myProject, getAuthDataHolder(), myIndicator, expected, true, GIST_DESCRIPTION, null);
     assertNotNull(url);
     GIST_ID = url.substring(url.lastIndexOf('/') + 1);
 
@@ -44,7 +49,9 @@
   public void testAnonymous() throws Throwable {
     List<FileContent> expected = createContent();
 
-    String url = GithubCreateGistAction.createGist(myProject, GithubAuthData.createAnonymous(myHost), expected, true, GIST_DESCRIPTION, null);
+    String url = GithubCreateGistAction
+      .createGist(myProject, new GithubAuthDataHolder(GithubAuthData.createAnonymous(myHost)), myIndicator, expected, true,
+                  GIST_DESCRIPTION, null);
     assertNotNull(url);
     GIST_ID = url.substring(url.lastIndexOf('/') + 1);
 
@@ -62,7 +69,8 @@
   public void testUnusedFilenameField() throws Throwable {
     List<FileContent> expected = createContent();
 
-    String url = GithubCreateGistAction.createGist(myProject, myGitHubSettings.getAuthData(), expected, true, GIST_DESCRIPTION, "filename");
+    String url =
+      GithubCreateGistAction.createGist(myProject, getAuthDataHolder(), myIndicator, expected, true, GIST_DESCRIPTION, "filename");
     assertNotNull(url);
     GIST_ID = url.substring(url.lastIndexOf('/') + 1);
 
@@ -77,7 +85,8 @@
     List<FileContent> content = Collections.singletonList(new FileContent("file.txt", "file.txt content"));
     List<FileContent> expected = Collections.singletonList(new FileContent("filename", "file.txt content"));
 
-    String url = GithubCreateGistAction.createGist(myProject, myGitHubSettings.getAuthData(), content, true, GIST_DESCRIPTION, "filename");
+    String url =
+      GithubCreateGistAction.createGist(myProject, getAuthDataHolder(), myIndicator, content, true, GIST_DESCRIPTION, "filename");
     assertNotNull(url);
     GIST_ID = url.substring(url.lastIndexOf('/') + 1);
 
@@ -91,7 +100,7 @@
   public void testPublic() throws Throwable {
     List<FileContent> expected = createContent();
 
-    String url = GithubCreateGistAction.createGist(myProject, myGitHubSettings.getAuthData(), expected, false, GIST_DESCRIPTION, null);
+    String url = GithubCreateGistAction.createGist(myProject, getAuthDataHolder(), myIndicator, expected, false, GIST_DESCRIPTION, null);
     assertNotNull(url);
     GIST_ID = url.substring(url.lastIndexOf('/') + 1);
 
@@ -105,33 +114,35 @@
   public void testEmpty() throws Throwable {
     List<FileContent> expected = Collections.emptyList();
 
-    String url = GithubCreateGistAction.createGist(myProject, myGitHubSettings.getAuthData(), expected, true, GIST_DESCRIPTION, null);
+    String url = GithubCreateGistAction.createGist(myProject, getAuthDataHolder(), myIndicator, expected, true, GIST_DESCRIPTION, null);
     assertNull("Gist was created", url);
 
     checkNotification(NotificationType.WARNING, "Can't create Gist", "Can't create empty gist");
   }
 
   public void testWrongLogin() throws Throwable {
-    registerDefaultLoginDialogHandler();
+    registerCancelingLoginDialogHandler();
 
     List<FileContent> expected = createContent();
 
     GithubAuthData auth = myGitHubSettings.getAuthData();
     GithubAuthData myAuth = GithubAuthData.createBasicAuth(auth.getHost(), myLogin1 + "some_suffix", myPassword);
-    String url = GithubCreateGistAction.createGist(myProject, myAuth, expected, true, GIST_DESCRIPTION, null);
+    String url =
+      GithubCreateGistAction.createGist(myProject, new GithubAuthDataHolder(myAuth), myIndicator, expected, true, GIST_DESCRIPTION, null);
     assertNull("Gist was created", url);
 
     checkNotification(NotificationType.ERROR, "Can't create Gist", null);
   }
 
   public void testWrongPassword() throws Throwable {
-    registerDefaultLoginDialogHandler();
+    registerCancelingLoginDialogHandler();
 
     List<FileContent> expected = createContent();
 
     GithubAuthData auth = myGitHubSettings.getAuthData();
     GithubAuthData myAuth = GithubAuthData.createBasicAuth(auth.getHost(), myLogin1, myPassword + "some_suffix");
-    String url = GithubCreateGistAction.createGist(myProject, myAuth, expected, true, GIST_DESCRIPTION, null);
+    String url =
+      GithubCreateGistAction.createGist(myProject, new GithubAuthDataHolder(myAuth), myIndicator, expected, true, GIST_DESCRIPTION, null);
     assertNull("Gist was created", url);
 
     checkNotification(NotificationType.ERROR, "Can't create Gist", null);
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
index 5e785fa..17a0c68 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
@@ -25,6 +25,7 @@
 import org.jetbrains.plugins.github.api.GithubGist;
 import org.jetbrains.plugins.github.test.GithubTest;
 import org.jetbrains.plugins.github.ui.GithubLoginDialog;
+import org.jetbrains.plugins.github.util.GithubAuthDataHolder;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -51,6 +52,11 @@
     deleteGist();
   }
 
+  @NotNull
+  protected GithubAuthDataHolder getAuthDataHolder() {
+    return new GithubAuthDataHolder(myGitHubSettings.getAuthData());
+  }
+
   protected void deleteGist() throws IOException {
     if (GIST_ID != null) {
       GithubApiUtil.deleteGist(myGitHubSettings.getAuthData(), GIST_ID);
@@ -133,7 +139,7 @@
     assertTrue("Gist content differs from sample", Comparing.haveEqualElements(expected, actual));
   }
 
-  protected void registerDefaultLoginDialogHandler() {
+  protected void registerCancelingLoginDialogHandler() {
     myDialogManager.registerDialogHandler(GithubLoginDialog.class, new TestDialogHandler<GithubLoginDialog>() {
       @Override
       public int handleDialog(GithubLoginDialog dialog) {
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubUrlUtilTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubUrlUtilTest.java
index ce187b7..636d14d 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubUrlUtilTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubUrlUtilTest.java
@@ -90,7 +90,7 @@
     });
   }
 
-  public void testIsGithubUrl() throws Throwable {
+  public void testIsGithubUrl1() throws Throwable {
     TestCase<Boolean> tests = new TestCase<Boolean>();
 
     tests.add("http://github.com/user/repo", true);
@@ -118,13 +118,50 @@
     runTestCase(tests, new Convertor<String, Boolean>() {
       @Override
       public Boolean convert(String in) {
-        return isGithubUrl(in, removeTrailingSlash(removeProtocolPrefix("https://github.com/")));
+        return isGithubUrl(in, "https://github.com/");
       }
     });
     runTestCase(tests, new Convertor<String, Boolean>() {
       @Override
       public Boolean convert(String in) {
-        return isGithubUrl(in, removeTrailingSlash(removeProtocolPrefix("http://GitHub.com")));
+        return isGithubUrl(in, "http://GitHub.com");
+      }
+    });
+  }
+
+  public void testIsGithubUrl2() throws Throwable {
+    TestCase<Boolean> tests = new TestCase<Boolean>();
+
+    tests.add("http://git.code.example.co.jp/user/repo", true);
+    tests.add("https://git.code.example.co.jp/user/repo", true);
+    tests.add("git://git.code.example.co.jp/user/repo", true);
+    tests.add("git@git.code.example.co.jp:user/repo", true);
+
+    tests.add("http://git.code.example.co/user/repo", false);
+    tests.add("http://code.example.co.jp/user/repo", false);
+
+    runTestCase(tests, new Convertor<String, Boolean>() {
+      @Override
+      public Boolean convert(String in) {
+        return isGithubUrl(in, "git.code.example.co.jp");
+      }
+    });
+    runTestCase(tests, new Convertor<String, Boolean>() {
+      @Override
+      public Boolean convert(String in) {
+        return isGithubUrl(in, "http://git.code.example.co.jp");
+      }
+    });
+    runTestCase(tests, new Convertor<String, Boolean>() {
+      @Override
+      public Boolean convert(String in) {
+        return isGithubUrl(in, "https://git.code.example.co.jp/github/server");
+      }
+    });
+    runTestCase(tests, new Convertor<String, Boolean>() {
+      @Override
+      public Boolean convert(String in) {
+        return isGithubUrl(in, "git.code.example.co.jp/api");
       }
     });
   }
diff --git a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
index 2c9496e..1f7635d 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
@@ -210,7 +210,7 @@
     myAuth = GithubAuthData.createBasicAuth(host, login1, password);
 
     myGitHubSettings = GithubSettings.getInstance();
-    myGitHubSettings.setCredentials(myHost, myAuth, false);
+    myGitHubSettings.setAuthData(myAuth, false);
 
     myDialogManager = (TestDialogManager)ServiceManager.getService(DialogManager.class);
     myNotificator = (TestNotificator)ServiceManager.getService(myProject, Notificator.class);
diff --git a/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml b/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml
index e471a6a..313b631 100644
--- a/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml
+++ b/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml
@@ -13,6 +13,7 @@
     <orderEntry type="module" module-name="jps-model-serialization" />
     <orderEntry type="module" module-name="jps-model-impl" scope="TEST" />
     <orderEntry type="module" module-name="appEngine-runtime" />
+    <orderEntry type="module" module-name="jps-serialization-tests" scope="TEST" />
   </component>
 </module>
 
diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
index d8d3297..af83972 100644
--- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
+++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
@@ -19,14 +19,18 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.Consumer;
+import com.intellij.util.Function;
 import com.intellij.util.SystemProperties;
 import com.intellij.util.containers.ContainerUtilRt;
+import com.intellij.util.lang.UrlClassLoader;
 import gnu.trove.THashMap;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.groovy.compiler.rt.GroovyRtConstants;
 import org.jetbrains.jps.ModuleChunk;
 import org.jetbrains.jps.ProjectPaths;
 import org.jetbrains.jps.builders.BuildRootIndex;
@@ -63,6 +67,7 @@
  *         Date: 10/25/11
  */
 public class GroovyBuilder extends ModuleLevelBuilder {
+  private static final int ourOptimizeThreshold = Integer.parseInt(System.getProperty("groovyc.optimized.class.loading.threshold", "10"));
   private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.groovy.GroovyBuilder");
   private static final Key<Boolean> CHUNK_REBUILD_ORDERED = Key.create("CHUNK_REBUILD_ORDERED");
   private static final Key<Map<String, String>> STUB_TO_SRC = Key.create("STUB_TO_SRC");
@@ -86,6 +91,7 @@
                                            ModuleChunk chunk,
                                            DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
                                            OutputConsumer outputConsumer) throws ProjectBuildException {
+    long start = 0;
     try {
       JpsGroovySettings settings = JpsGroovySettings.getSettings(context.getProjectDescriptor().getProject());
 
@@ -102,8 +108,10 @@
         return ExitCode.ABORT;
       }
 
+      start = System.currentTimeMillis();
       final Set<String> toCompilePaths = getPathsToCompile(toCompile);
-      
+      boolean optimizeClassLoading = ourOptimizeThreshold != 0 && toCompilePaths.size() >= ourOptimizeThreshold;
+
       Map<String, String> class2Src = buildClassToSourceMap(chunk, context, toCompilePaths, finalOutputs);
 
       final String encoding = context.getProjectDescriptor().getEncodingConfiguration().getPreferredModuleChunkEncoding(chunk);
@@ -117,10 +125,18 @@
       String compilerOutput = generationOutputs.get(chunk.representativeTarget());
 
       String finalOutput = FileUtil.toSystemDependentName(finalOutputs.get(chunk.representativeTarget()));
+
+      Collection<String> classpath = generateClasspath(context, chunk);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Optimized class loading: " + optimizeClassLoading);
+        LOG.debug("Groovyc classpath: " + classpath);
+      }
+
       final File tempFile = GroovycOSProcessHandler.fillFileWithGroovycParameters(
-        compilerOutput, toCompilePaths, finalOutput, class2Src, encoding, patchers
+        compilerOutput, toCompilePaths, finalOutput, class2Src, encoding, patchers,
+        optimizeClassLoading ? StringUtil.join(classpath, File.pathSeparator) : ""
       );
-      final GroovycOSProcessHandler handler = runGroovyc(context, chunk, tempFile, settings);
+      final GroovycOSProcessHandler handler = runGroovyc(context, chunk, tempFile, settings, classpath, optimizeClassLoading);
 
       Map<ModuleBuildTarget, Collection<GroovycOSProcessHandler.OutputItem>>
         compiled = processCompiledFiles(context, chunk, generationOutputs, compilerOutput, handler);
@@ -147,8 +163,11 @@
       throw new ProjectBuildException(e);
     }
     finally {
+      if (start > 0 && LOG.isDebugEnabled()) {
+        LOG.debug(myBuilderName + " took " + (System.currentTimeMillis() - start) + " on " + chunk.getName());
+      }
       if (!myForStubs) {
-        FILES_MARKED_DIRTY_FOR_NEXT_ROUND.set(context, null); 
+        FILES_MARKED_DIRTY_FOR_NEXT_ROUND.set(context, null);
       }
     }
   }
@@ -169,15 +188,24 @@
   }
 
   private GroovycOSProcessHandler runGroovyc(final CompileContext context,
-                                             ModuleChunk chunk,
+                                             final ModuleChunk chunk,
                                              File tempFile,
-                                             final JpsGroovySettings settings) throws IOException {
-    ArrayList<String> classpath = new ArrayList<String>(generateClasspath(context, chunk));
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Groovyc classpath: " + classpath);
+                                             final JpsGroovySettings settings,
+                                             Collection<String> compilationClassPath,
+                                             boolean optimizeClassLoading) throws IOException {
+    List<String> classpath = new ArrayList<String>();
+    if (optimizeClassLoading) {
+      classpath.add(getGroovyRtRoot().getPath());
+      classpath.add(ClasspathBootstrap.getResourcePath(Function.class));
+      classpath.add(ClasspathBootstrap.getResourcePath(UrlClassLoader.class));
+      classpath.add(ClasspathBootstrap.getResourceFile(THashMap.class).getPath());
+    } else {
+      classpath.addAll(compilationClassPath);
     }
 
-    List<String> programParams = ContainerUtilRt.newArrayList(myForStubs ? "stubs" : "groovyc", tempFile.getPath());
+    List<String> programParams = ContainerUtilRt.newArrayList(optimizeClassLoading ? GroovyRtConstants.OPTIMIZE : "do_not_optimize",
+                                                              myForStubs ? "stubs" : "groovyc",
+                                                              tempFile.getPath());
     if (settings.invokeDynamic) {
       programParams.add("--indy");
     }
@@ -203,7 +231,7 @@
     final Process process = Runtime.getRuntime().exec(ArrayUtil.toStringArray(cmd));
     final Consumer<String> updater = new Consumer<String>() {
       public void consume(String s) {
-        context.processMessage(new ProgressMessage(s));
+        context.processMessage(new ProgressMessage(s + " [" + chunk.getPresentableShortName() + "]"));
       }
     };
     final GroovycOSProcessHandler handler = new GroovycOSProcessHandler(process, updater) {
@@ -403,7 +431,7 @@
             callback.associate(outputPath, sourcePath, new ClassReader(FileUtil.loadFileBytes(outputFile)));
           }
           catch (Throwable e) {
-            // need this to make sure that unexpected errors in, for example, ASM will not ruin the compilation  
+            // need this to make sure that unexpected errors in, for example, ASM will not ruin the compilation
             final String message = "Class dependency information may be incomplete! Error parsing generated class " + item.outputPath;
             LOG.info(message, e);
             context.processMessage(new CompilerMessage(
diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java
index 9a5a3d0..a03067d 100644
--- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java
+++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java
@@ -219,10 +219,12 @@
     if (unparsedBuffer.length() != 0) {
       String msg = unparsedBuffer.toString();
       if (msg.contains(GroovyRtConstants.NO_GROOVY)) {
-        msg = "Cannot compile Groovy files: no Groovy library is defined for module '" + moduleName + "'";
+        messages.add(new CompilerMessage("", BuildMessage.Kind.ERROR,
+                                         "Cannot compile Groovy files: no Groovy library is defined for module '" + moduleName + "'"));
+      } else {
+        messages.add(new CompilerMessage("Groovyc", BuildMessage.Kind.INFO, msg));
       }
 
-      messages.add(new CompilerMessage("Groovyc", BuildMessage.Kind.INFO, msg));
     }
 
     final int exitValue = getProcess().exitValue();
@@ -245,11 +247,17 @@
   public static File fillFileWithGroovycParameters(final String outputDir,
                                                    final Collection<String> changedSources,
                                                    String finalOutput,
-                                                   Map<String, String> class2Src, @Nullable final String encoding, List<String> patchers) throws IOException {
+                                                   Map<String, String> class2Src,
+                                                   @Nullable final String encoding,
+                                                   List<String> patchers,
+                                                   String classpath) throws IOException {
     File tempFile = FileUtil.createTempFile("ideaGroovyToCompile", ".txt", true);
 
     final Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempFile)));
     try {
+      writer.write(classpath);
+      writer.write("\n");
+
       for (String file : changedSources) {
         writer.write(GroovyRtConstants.SRC_FILE + "\n");
         writer.write(file);
diff --git a/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/GroovyRtConstants.java b/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/GroovyRtConstants.java
index d146db0..37583dd 100644
--- a/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/GroovyRtConstants.java
+++ b/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/GroovyRtConstants.java
@@ -36,4 +36,5 @@
   public static final String PRESENTABLE_MESSAGE = "@#$%@# Presentable:";
   public static final String CLEAR_PRESENTABLE = "$@#$%^ CLEAR_PRESENTABLE";
   public static final String NO_GROOVY = "Cannot compile Groovy files: no Groovy library is defined";
+  public static final String OPTIMIZE = "optimize";
 }
diff --git a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java
index 835c91d..bb374cd 100644
--- a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java
+++ b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java
@@ -39,7 +39,8 @@
  * @author peter
  */
 public class DependentGroovycRunner {
-  static boolean runGroovyc(boolean forStubs, File argsFile) {
+  public static boolean runGroovyc(boolean forStubs, String argsPath) {
+    File argsFile = new File(argsPath);
     final CompilerConfiguration config = new CompilerConfiguration();
     config.setClasspath("");
     config.setOutput(new PrintWriter(System.err));
@@ -113,8 +114,9 @@
       stream = new FileInputStream(argsFile);
       reader = new BufferedReader(new InputStreamReader(stream));
 
-      String line;
+      reader.readLine(); // skip classpath
 
+      String line;
       while ((line = reader.readLine()) != null) {
         if (!GroovyRtConstants.SRC_FILE.equals(line)) {
           break;
diff --git a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovyCompilerUtil.java b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovyCompilerUtil.java
deleted file mode 100644
index fc7a74c..0000000
--- a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovyCompilerUtil.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2000-2008 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 org.jetbrains.groovy.compiler.rt;
-
-import org.codehaus.groovy.control.CompilerConfiguration;
-
-import java.net.URL;
-import java.net.MalformedURLException;
-import java.util.List;
-import java.io.File;
-
-/**
- * @author ilyas
- */
-public class GroovyCompilerUtil {
-  static URL[] convertClasspathToUrls(CompilerConfiguration compilerConfiguration) {
-    try {
-      return classpathAsUrls(compilerConfiguration);
-    } catch (MalformedURLException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  static URL[] classpathAsUrls(CompilerConfiguration compilerConfiguration) throws MalformedURLException {
-    List classpath = compilerConfiguration.getClasspath();
-    URL[] classpathUrls = new URL[classpath.size()];
-    for (int i = 0; i < classpathUrls.length; i++) {
-      String classpathEntry = (String) classpath.get(i);
-      classpathUrls[i] = new File(classpathEntry).toURI().toURL();
-    }
-    return classpathUrls;
-  }
-}
diff --git a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovycRunner.java b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovycRunner.java
index 3d7e8eb..aaa42bc 100644
--- a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovycRunner.java
+++ b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovycRunner.java
@@ -15,7 +15,16 @@
 
 package org.jetbrains.groovy.compiler.rt;
 
+import com.intellij.util.lang.UrlClassLoader;
+import sun.misc.URLClassPath;
+
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.*;
 
 /**
  * @author: Dmitry.Krasilschikov
@@ -57,24 +66,28 @@
     }
     */
 
-    if (args.length != 2) {
-      if (args.length != 3 || !"--indy".equals(args[2])) {
+    if (args.length != 3) {
+      if (args.length != 4 || !"--indy".equals(args[3])) {
         System.err.println("There is no arguments for groovy compiler");
         System.exit(1);
       }
       System.setProperty("groovy.target.indy", "true");
     }
 
-    final boolean forStubs = "stubs".equals(args[0]);
-    final File argsFile = new File(args[1]);
+    final boolean optimize = GroovyRtConstants.OPTIMIZE.equals(args[0]);
+    final boolean forStubs = "stubs".equals(args[1]);
+    String argPath = args[2];
 
-    if (!argsFile.exists()) {
+    if (!new File(argPath).exists()) {
       System.err.println("Arguments file for groovy compiler not found");
       System.exit(1);
     }
 
+    ClassLoader loader = optimize ? buildMainLoader(argPath) : GroovycRunner.class.getClassLoader();
+    Thread.currentThread().setContextClassLoader(loader);
+
     try {
-      Class.forName("org.codehaus.groovy.control.CompilationUnit");
+      Class.forName("org.codehaus.groovy.control.CompilationUnit", true, loader);
     }
     catch (Throwable e) {
       System.err.println(GroovyRtConstants.NO_GROOVY);
@@ -82,7 +95,9 @@
     }
 
     try {
-      DependentGroovycRunner.runGroovyc(forStubs, argsFile);
+      Class<?> aClass = Class.forName("org.jetbrains.groovy.compiler.rt.DependentGroovycRunner", true, loader);
+      Method method = aClass.getDeclaredMethod("runGroovyc", boolean.class, String.class);
+      method.invoke(null, forStubs, argPath);
     }
     catch (Throwable e) {
       e.printStackTrace();
@@ -102,4 +117,43 @@
     }
     */
   }
+
+  private static ClassLoader buildMainLoader(String argsPath) {
+    Set<URL> bootstrapUrls = new HashSet<URL>();
+    try {
+      Method method = ClassLoader.class.getDeclaredMethod("getBootstrapClassPath");
+      method.setAccessible(true);
+      URLClassPath ucp = (URLClassPath)method.invoke(null);
+      Collections.addAll(bootstrapUrls, ucp.getURLs());
+    }
+    catch (Exception e) {
+      e.printStackTrace();
+    }
+
+    final List<URL> urls = new ArrayList<URL>();
+    try {
+      //noinspection IOResourceOpenedButNotSafelyClosed
+      BufferedReader reader = new BufferedReader(new FileReader(argsPath));
+      String classpath = reader.readLine();
+      for (String s : classpath.split(File.pathSeparator)) {
+        URL url = new File(s).toURI().toURL();
+        if (!bootstrapUrls.contains(url)) {
+          urls.add(url);
+        }
+      }
+      reader.close();
+    }
+    catch (IOException e) {
+      e.printStackTrace();
+      System.exit(1);
+    }
+
+    final ClassLoader[] ref = new ClassLoader[1];
+    new Runnable() {
+      public void run() {
+        ref[0] = UrlClassLoader.build().urls(urls).useCache().get();
+      }
+    }.run();
+    return ref[0];
+  }
 }
diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml
index f069024..68d8b51 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -79,6 +79,7 @@
 
     <extensionPoint name="convertToJava.customMethodInvocator" interface="org.jetbrains.plugins.groovy.refactoring.convertToJava.invocators.CustomMethodInvocator"/>
 
+    <extensionPoint name="signatureHintProcessor" interface="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.SignatureHintProcessor"/>
   </extensionPoints>
 
   <extensions defaultExtensionNs="org.intellij.groovy">
@@ -150,7 +151,30 @@
 
     <variableEnhancer implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhancer"/>
     <variableEnhancer implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureAsAnonymousParameterEnhancer"/>
+    <variableEnhancer implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParamsEnhancer"/>
 
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.FromStringHintProcessor"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.SimpleTypeHintProcessor"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.MapEntryOrKeyValueHintProcessor"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.FromAbstractTypeMethodsHintProcessor"/>
+
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.FirstParamHintProcessor"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.FirstParamHintProcessor$FirstGeneric"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.FirstParamHintProcessor$SecondGeneric"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.FirstParamHintProcessor$ThirdGeneric"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.FirstParamHintProcessor$Component"/>
+
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.SecondParamHintProcessor"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.SecondParamHintProcessor$FirstGeneric"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.SecondParamHintProcessor$SecondGeneric"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.SecondParamHintProcessor$ThirdGeneric"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.SecondParamHintProcessor$Component"/>
+
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ThirdParamHintProcessor"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ThirdParamHintProcessor$FirstGeneric"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ThirdParamHintProcessor$SecondGeneric"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ThirdParamHintProcessor$ThirdGeneric"/>
+    <signatureHintProcessor implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ThirdParamHintProcessor$Component"/>
 
     <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrContainerTypeConverter"/>
     <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrStringTypeConverter"/>
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
index dee417b..4f7ebf4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
@@ -168,9 +168,12 @@
 
   @Override
   public void visitNamedArgument(GrNamedArgument argument) {
-    final PsiElement parent = argument.getParent().getParent();
-    if (parent instanceof GrIndexProperty) {
-      myHolder.createErrorAnnotation(argument, GroovyBundle.message("named.arguments.are.not.allowed.inside.index.operations"));
+    PsiElement parent = argument.getParent();
+    if (parent instanceof GrArgumentList) {
+      final PsiElement pparent = parent.getParent();
+      if (pparent instanceof GrIndexProperty) {
+        myHolder.createErrorAnnotation(argument, GroovyBundle.message("named.arguments.are.not.allowed.inside.index.operations"));
+      }
     }
   }
 
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java
index a99f62d..4ab96f0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.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.
@@ -49,7 +49,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Set;
 
 /**
  * @author Max Medvedev
@@ -138,9 +137,9 @@
         if (project.isDisposed()) return;
 
         final String name = ref.getReferenceName();
-        final Set<PsiType> types = GroovyExpectedTypesProvider.getDefaultExpectedTypes(ref);
+        final List<PsiType> types = GroovyExpectedTypesProvider.getDefaultExpectedTypes(ref);
 
-        PsiType unboxed = types.isEmpty() ? null : TypesUtil.unboxPrimitiveTypeWrapper(types.iterator().next());
+        PsiType unboxed = types.isEmpty() ? null : TypesUtil.unboxPrimitiveTypeWrapper(types.get(0));
         @NotNull final PsiType type = unboxed != null ? unboxed : PsiType.getJavaLangObject(ref.getManager(), ref.getResolveScope());
 
         if (method instanceof GrMethod) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
index 3d658f0..c19311d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
@@ -109,4 +109,6 @@
 replace.qualified.name.with.import=Replace qualified name with import
 highlight.assignments.from.void=Highlight assignments from void type
 comments.count.as.content=Comments count as content
-ignore.when.catch.parameter.is.named.ignore.or.ignored=Ignore when catch parameter is named ignore or ignored
\ No newline at end of file
+ignore.when.catch.parameter.is.named.ignore.or.ignored=Ignore when catch parameter is named ignore or ignored
+no.applicable.signature.found=No applicable signature found
+expected.type.0=Expected {0}
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
index 970b391..b0d47a0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
@@ -24,6 +24,7 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.Pair;
 import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
 import com.intellij.psi.*;
@@ -70,8 +71,10 @@
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*;
 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
 import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
 import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
 import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
@@ -79,6 +82,7 @@
 import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
 import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhancer;
+import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParamsEnhancer;
 import org.jetbrains.plugins.groovy.lang.psi.util.*;
 import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
 import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
@@ -242,7 +246,6 @@
 
     @Override
     public void visitReturnStatement(GrReturnStatement returnStatement) {
-      super.visitReturnStatement(returnStatement);
       final GrExpression value = returnStatement.getReturnValue();
       if (value == null || isNewInstanceInitialingByTuple(value)) return;
 
@@ -254,7 +257,6 @@
 
     @Override
     public void visitExpression(GrExpression expression) {
-      super.visitExpression(expression);
       if (PsiUtil.isExpressionStatement(expression)) {
         final PsiType returnType = PsiImplUtil.inferReturnType(expression);
         final GrControlFlowOwner flowOwner = ControlFlowUtils.findControlFlowOwner(expression);
@@ -274,8 +276,6 @@
 
     @Override
     public void visitAssignmentExpression(GrAssignmentExpression assignment) {
-      super.visitAssignmentExpression(assignment);
-
       GrExpression lValue = assignment.getLValue();
       if (lValue instanceof GrIndexProperty) return;
       if (!PsiUtil.mightBeLValue(lValue)) return;
@@ -363,8 +363,6 @@
 
     @Override
     public void visitVariable(GrVariable variable) {
-      super.visitVariable(variable);
-
       PsiType varType = variable.getType();
 
       PsiElement parent = variable.getParent();
@@ -430,7 +428,6 @@
 
     @Override
     public void visitNewExpression(GrNewExpression newExpression) {
-      super.visitNewExpression(newExpression);
       if (newExpression.getArrayCount() > 0) return;
 
       GrCodeReferenceElement refElement = newExpression.getReferenceElement();
@@ -502,7 +499,6 @@
 
     @Override
     public void visitListOrMap(GrListOrMap listOrMap) {
-      super.visitListOrMap(listOrMap);
 
       final PsiReference reference = listOrMap.getReference();
       if (!(reference instanceof LiteralConstructorReference)) return;
@@ -515,7 +511,6 @@
 
     @Override
     public void visitThrowStatement(GrThrowStatement throwStatement) {
-      super.visitThrowStatement(throwStatement);
 
       final GrExpression exception = throwStatement.getException();
       if (exception != null) {
@@ -557,7 +552,6 @@
 
     @Override
     public void visitConstructorInvocation(GrConstructorInvocation invocation) {
-      super.visitConstructorInvocation(invocation);
       GrConstructorInvocationInfo info = new GrConstructorInvocationInfo(invocation);
       checkConstructorCall(info);
       checkNamedArgumentsType(info);
@@ -565,8 +559,6 @@
 
     @Override
     public void visitIndexProperty(GrIndexProperty expression) {
-      super.visitIndexProperty(expression);
-
       checkIndexProperty(new GrIndexPropertyInfo(expression));
     }
 
@@ -651,25 +643,21 @@
 
     @Override
     public void visitMethodCallExpression(GrMethodCallExpression methodCallExpression) {
-      super.visitMethodCallExpression(methodCallExpression);
       checkMethodCall(new GrMethodCallInfo(methodCallExpression));
     }
 
     @Override
     public void visitApplicationStatement(GrApplicationStatement applicationStatement) {
-      super.visitApplicationStatement(applicationStatement);
       checkMethodCall(new GrMethodCallInfo(applicationStatement));
     }
 
     @Override
     public void visitBinaryExpression(GrBinaryExpression binary) {
-      super.visitBinaryExpression(binary);
       checkOperator(new GrBinaryExprInfo(binary));
     }
 
     @Override
     public void visitEnumConstant(GrEnumConstant enumConstant) {
-      super.visitEnumConstant(enumConstant);
       GrEnumConstantInfo info = new GrEnumConstantInfo(enumConstant);
       checkConstructorCall(info);
       checkNamedArgumentsType(info);
@@ -710,6 +698,60 @@
       }
     }
 
+    @Override
+    public void visitParameterList(final GrParameterList parameterList) {
+      PsiElement parent = parameterList.getParent();
+      if (parent instanceof GrClosableBlock) {
+
+        GrParameter[] parameters = parameterList.getParameters();
+        if (parameters.length > 0) {
+          List<PsiType[]> signatures = ClosureParamsEnhancer.findFittingSignatures((GrClosableBlock)parent);
+          final List<PsiType> paramTypes = ContainerUtil.map(parameters, new Function<GrParameter, PsiType>() {
+            @Override
+            public PsiType fun(GrParameter parameter) {
+              return parameter.getType();
+            }
+          });
+
+          if (signatures.size() > 1) {
+            PsiType[] fittingSignature = ContainerUtil.find(signatures, new Condition<PsiType[]>() {
+              @Override
+              public boolean value(PsiType[] types) {
+                for (int i = 0; i < types.length; i++) {
+                  if (!typesAreEqual(types[i], paramTypes.get(i), parameterList)) {
+                    return false;
+                  }
+                }
+                return true;
+              }
+            });
+
+            if (fittingSignature == null) {
+              registerError(parameterList, GroovyInspectionBundle.message("no.applicable.signature.found"));
+            }
+          }
+          else if (signatures.size() == 1) {
+            PsiType[] types = signatures.get(0);
+            for (int i = 0; i < types.length; i++) {
+              GrTypeElement typeElement = parameters[i].getTypeElementGroovy();
+              if (typeElement == null) continue;
+              PsiType expected = types[i];
+              PsiType actual = paramTypes.get(i);
+              if (!typesAreEqual(expected, actual, parameterList)) {
+                registerError(typeElement, GroovyInspectionBundle.message("expected.type.0", expected.getPresentableText()));
+              }
+            }
+          }
+        }
+      }
+    }
+
+    private static boolean typesAreEqual(@NotNull PsiType expected, @NotNull PsiType actual, @NotNull PsiElement context) {
+      return TypesUtil.isAssignableByMethodCallConversion(expected, actual, context) &&
+             TypesUtil.isAssignableByMethodCallConversion(actual, expected, context);
+    }
+
+
     /**
      * checks only children of e
      */
@@ -1020,6 +1062,11 @@
     private void highlightUnknownArgs(@NotNull CallInfo info) {
       registerError(info.getElementToHighlight(), GroovyBundle.message("cannot.infer.argument.types"), LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.WEAK_WARNING);
     }
+
+    @Override
+    public void visitElement(GroovyPsiElement element) {
+      //do nothing
+    }
   }
 
   @Nullable
@@ -1108,12 +1155,6 @@
                                  Object... args) {
       registerError(location, (String)args[0], LocalQuickFix.EMPTY_ARRAY, highlightType);
     }
-
-
-    @Override
-    public void visitElement(GroovyPsiElement element) {
-      //do nothing
-    }
   }
 
   private static final ThreadLocal<AnnotatingVisitor> visitor = new ThreadLocal<AnnotatingVisitor>() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrReassignedInClosureLocalVarInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrReassignedInClosureLocalVarInspection.java
index 82a688f..400c0a3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrReassignedInClosureLocalVarInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrReassignedInClosureLocalVarInspection.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.
@@ -21,12 +21,16 @@
 import com.intellij.psi.PsiType;
 import org.jetbrains.annotations.Nls;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.codeInsight.GrReassignedLocalVarsChecker;
 import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
 import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
 import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
+import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
 import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
 import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
 import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
 
@@ -66,18 +70,38 @@
         final PsiElement resolved = referenceExpression.resolve();
         if (!GroovyRefactoringUtil.isLocalVariable(resolved)) return;
 
-        if (isOtherTypeOrDifferent(referenceExpression, (GrVariable)resolved) ) {
-          final String message = message("local.var.0.is.reassigned", ((GrNamedElement)resolved).getName());
+        final PsiType checked = GrReassignedLocalVarsChecker.getReassignedVarType(referenceExpression, false);
+        if (checked == null) return;
+
+        final GrControlFlowOwner varFlowOwner = ControlFlowUtils.findControlFlowOwner(resolved);
+        final GrControlFlowOwner refFlorOwner = ControlFlowUtils.findControlFlowOwner(referenceExpression);
+        if (isOtherScopeAndType(referenceExpression, checked, varFlowOwner, refFlorOwner)) {
+          String flowDescription = getFlowDescription(refFlorOwner);
+          final String message = message("local.var.0.is.reassigned", ((GrNamedElement)resolved).getName(), flowDescription);
           registerError(referenceExpression, message, LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
         }
       }
     };
   }
 
-  private static boolean isOtherTypeOrDifferent(@NotNull GrReferenceExpression referenceExpression, GrVariable resolved) {
-    if (ControlFlowUtils.findControlFlowOwner(referenceExpression) != ControlFlowUtils.findControlFlowOwner(resolved)) return true;
+  private static boolean isOtherScopeAndType(GrReferenceExpression referenceExpression,
+                                             PsiType checked,
+                                             GrControlFlowOwner varFlowOwner,
+                                             GrControlFlowOwner refFlorOwner) {
+    return varFlowOwner != refFlorOwner && !TypesUtil.isAssignable(referenceExpression.getType(), checked, referenceExpression);
+  }
 
-    final PsiType currentType = referenceExpression.getType();
-    return currentType != null && currentType != PsiType.NULL && !ControlFlowUtils.findAccess(resolved, referenceExpression, false, true).isEmpty();
+  private static String getFlowDescription(GrControlFlowOwner refFlorOwner) {
+    String flowDescription;
+    if (refFlorOwner instanceof GrClosableBlock) {
+      flowDescription = message("closure");
+    }
+    else if (refFlorOwner instanceof GrAnonymousClassDefinition) {
+      flowDescription = message("anonymous.class");
+    }
+    else {
+      flowDescription = message("other.scope");
+    }
+    return flowDescription;
   }
 }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java
index 31a9740..78e3886 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.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.
@@ -49,7 +49,6 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * @author ven
@@ -125,9 +124,7 @@
       }
     }
     else {
-      final Set<PsiType> expectedTypes = GroovyExpectedTypesProvider.getDefaultExpectedTypes(closure);
-
-      for (PsiType expectedType : expectedTypes) {
+      for (PsiType expectedType : GroovyExpectedTypesProvider.getDefaultExpectedTypes(closure)) {
         if (TypesUtil.isPsiClassTypeToClosure(expectedType)) {
           PsiType[] parameters = ((PsiClassType)expectedType).getParameters();
           if (parameters.length == 1) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GroovyUntypedAccessInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GroovyUntypedAccessInspection.java
index d0b051e..f4b380b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GroovyUntypedAccessInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GroovyUntypedAccessInspection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -27,6 +27,7 @@
 import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
 
 import static org.jetbrains.plugins.groovy.annotator.GrHighlightUtil.isDeclarationAssignment;
 
@@ -35,8 +36,37 @@
  */
 public class GroovyUntypedAccessInspection extends BaseInspection {
 
+  @NotNull
   protected BaseInspectionVisitor buildVisitor() {
-    return new Visitor();
+    return new BaseInspectionVisitor() {
+      @Override
+      public void visitReferenceExpression(GrReferenceExpression refExpr) {
+        super.visitReferenceExpression(refExpr);
+
+        if (PsiUtil.isThisOrSuperRef(refExpr)) return;
+
+        GroovyResolveResult resolveResult = refExpr.advancedResolve();
+
+        PsiElement resolved = resolveResult.getElement();
+        if (resolved != null) {
+          if (isDeclarationAssignment(refExpr) || resolved instanceof PsiPackage) return;
+        }
+        else {
+          GrExpression qualifier = refExpr.getQualifierExpression();
+          if (qualifier == null && isDeclarationAssignment(refExpr)) return;
+        }
+
+        final PsiType refExprType = refExpr.getType();
+        if (refExprType == null) {
+          if (resolved != null) {
+            registerError(refExpr);
+          }
+        }
+        else if (refExprType instanceof PsiClassType && ((PsiClassType)refExprType).resolve() == null) {
+          registerError(refExpr);
+        }
+      }
+    };
   }
 
   @Nls
@@ -55,31 +85,4 @@
   protected String buildErrorString(Object... args) {
     return "Cannot determine type of '#ref'";
   }
-
-  private static class Visitor extends BaseInspectionVisitor {
-    @Override
-    public void visitReferenceExpression(GrReferenceExpression refExpr) {
-      super.visitReferenceExpression(refExpr);
-      GroovyResolveResult resolveResult = refExpr.advancedResolve();
-
-      PsiElement resolved = resolveResult.getElement();
-      if (resolved != null) {
-        if (isDeclarationAssignment(refExpr) || resolved instanceof PsiPackage) return;
-      }
-      else {
-        GrExpression qualifier = refExpr.getQualifierExpression();
-        if (qualifier == null && isDeclarationAssignment(refExpr)) return;
-      }
-
-      final PsiType refExprType = refExpr.getType();
-      if (refExprType == null) {
-        if (resolved != null) {
-          registerError(refExpr);
-        }
-      }
-      else if (refExprType instanceof PsiClassType && ((PsiClassType)refExprType).resolve() == null) {
-        registerError(refExpr);
-      }
-    }
-  }
 }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java
index 69450a8..505d88b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java
@@ -194,7 +194,7 @@
     try {
       fileWithParameters = GroovycOSProcessHandler
         .fillFileWithGroovycParameters(outputDir.getPath(), paths2Compile, FileUtil.toSystemDependentName(finalOutputDir.getPath()),
-                                       class2Src, encoding, patchers);
+                                       class2Src, encoding, patchers, "");
     }
     catch (IOException e) {
       LOG.info(e);
@@ -202,6 +202,7 @@
       return;
     }
 
+    parameters.getProgramParametersList().add("do_not_optimize");
     parameters.getProgramParametersList().add(forStubs ? "stubs" : "groovyc");
     parameters.getProgramParametersList().add(fileWithParameters.getPath());
     if (compilerConfiguration.isInvokeDynamic()) {
@@ -253,7 +254,7 @@
           if (sourceVirtualFile == null) {
             continue;
           }
-          
+
           if (indicator != null) {
             indicator.setText2(sourceVirtualFile.getName());
           }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java
index 8f9958b..5470ed0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.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.
@@ -129,6 +129,8 @@
    Methods to add new behavior
    *********************************************************** */
   public void property(Map<Object, Object> args) {
+    if (args == null) return;
+
     String name = (String)args.get("name");
     Object type = args.get("type");
     Object doc = args.get("doc");
@@ -156,6 +158,8 @@
   }
 
   public void constructor(Map<Object, Object> args) {
+    if (args == null) return;
+
     args.put("constructor", true);
     method(args);
   }
@@ -190,8 +194,7 @@
       ContainerUtil.map(argTypes, new Function<PsiType, Object>() {
         @Override
         public Object fun(PsiType type) {
-          String canonical = type.getCanonicalText();
-          return canonical != null ? canonical : type.getPresentableText();
+          return type.getCanonicalText();
         }
       }, types);
 
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
index 82cfe11..b852cd2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
@@ -28,6 +28,7 @@
 import com.intellij.openapi.roots.ProjectFileIndex;
 import com.intellij.openapi.roots.ProjectRootManager;
 import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.ModificationTracker;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Trinity;
 import com.intellij.openapi.util.io.FileUtil;
@@ -131,11 +132,13 @@
     return myDataIndexer;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<String> getKeyDescriptor() {
     return myKeyDescriptor;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return new MyInputFilter();
@@ -438,7 +441,7 @@
       @Override
       public Result<List<GroovyDslScript>> compute() {
         if (ourGdslStopped) {
-          return Result.create(Collections.<GroovyDslScript>emptyList(), Collections.emptyList());
+          return Result.create(Collections.<GroovyDslScript>emptyList(), ModificationTracker.NEVER_CHANGED);
         }
 
         int count = 0;
@@ -513,7 +516,7 @@
     }
 
     @Override
-    public boolean acceptInput(final VirtualFile file) {
+    public boolean acceptInput(@NotNull final VirtualFile file) {
       return "gdsl".equals(file.getExtension());
     }
   }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/blocks/GroovyBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/blocks/GroovyBlockGenerator.java
index bba1441..8a98eef 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/blocks/GroovyBlockGenerator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/blocks/GroovyBlockGenerator.java
@@ -405,7 +405,7 @@
       PsiElement psi = child.getPsi();
       if (psi instanceof GrLabeledStatement) {
         alignGroup(currentGroup, spock, classLevel);
-        currentGroup = ContainerUtil.newArrayList(/*(GrStatement)psi*/);
+        currentGroup = ContainerUtil.newArrayList();
         spock = true;
       }
       else if (currentGroup != null && spock && isTablePart(psi)) {
@@ -428,6 +428,10 @@
         currentGroup = null;
       }
     }
+
+    if (currentGroup != null) {
+      alignGroup(currentGroup, spock, classLevel);
+    }
   }
 
   private boolean shouldSkip(boolean classLevel, PsiElement psi) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java
index 4d1f239..c9f6f98 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java
@@ -287,8 +287,7 @@
       placeToInferType = (GrExpression)expression.getParent();
     }
 
-    final Set<PsiType> types = GroovyExpectedTypesProvider.getDefaultExpectedTypes(placeToInferType);
-    for (PsiType type : types) {
+    for (PsiType type : GroovyExpectedTypesProvider.getDefaultExpectedTypes(placeToInferType)) {
       if (type instanceof PsiArrayType) {
         final PsiType _type = GenericsUtil.eliminateWildcards(type);
         final LookupItem item = PsiTypeLookupItem.createLookupItem(_type, place, PsiTypeLookupItem.isDiamond(_type), ChooseTypeExpression.IMPORT_FIXER);
@@ -307,7 +306,7 @@
 
     final List<PsiClassType> expectedClassTypes = new SmartList<PsiClassType>();
 
-    for (PsiType psiType : types) {
+    for (PsiType psiType : GroovyExpectedTypesProvider.getDefaultExpectedTypes(placeToInferType)) {
       if (psiType instanceof PsiClassType) {
         PsiType type = GenericsUtil.eliminateWildcards(JavaCompletionUtil.originalize(psiType));
         final PsiClassType classType = (PsiClassType)type;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java
index 10e5c0b..e2e36d1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java
@@ -26,7 +26,6 @@
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.containers.hash.HashSet;
 import com.intellij.util.text.CharArrayUtil;
-import com.intellij.xml.util.XmlStringUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil;
@@ -387,11 +386,11 @@
         for (int j = 0; j < numParams; j++) {
           PsiParameter param = params[j];
 
-          int startOffset = XmlStringUtil.escapeString(buffer.toString()).length();
+          int startOffset = buffer.length();
 
           appendParameterText(param, substitutor, buffer);
 
-          int endOffset = XmlStringUtil.escapeString(buffer.toString()).length();
+          int endOffset = buffer.length();
 
           if (j < numParams - 1) {
             buffer.append(", ");
@@ -420,7 +419,7 @@
         for (int i = 0; i < parameters.length; i++) {
           if (i > 0) buffer.append(", ");
 
-          int startOffset = XmlStringUtil.escapeString(buffer.toString()).length();
+          int startOffset = buffer.length();
           final PsiType psiType = parameters[i].getType();
           if (psiType == null) {
             buffer.append("def");
@@ -430,7 +429,7 @@
           }
           buffer.append(' ').append(parameters[i].getName() != null ? parameters[i].getName() : "<unknown>");
 
-          int endOffset = XmlStringUtil.escapeString(buffer.toString()).length();
+          int endOffset = buffer.length();
 
           if (context.isUIComponentEnabled() &&
               (i == currentParameter || (i == parameters.length - 1 && ((GrClosureSignature)element).isVarargs() && currentParameter >= parameters.length))) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrField.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrField.java
index 0946bd5..6e3ea04 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrField.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrField.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -41,7 +41,5 @@
 
   @NotNull
   Map<String, NamedArgumentDescriptor> getNamedParameters();
-
-  void clearCaches();
 }
 
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java
index 09ce7cc..1d541a0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java
@@ -22,6 +22,7 @@
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.ArrayUtil;
+import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -52,14 +53,15 @@
 import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
 import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
 import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
-import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
 import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
 import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
 import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
 import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
 
@@ -97,12 +99,14 @@
       });
   }
 
-  public static Set<PsiType> getDefaultExpectedTypes(@NotNull GrExpression element) {
-    final LinkedHashSet<PsiType> result = new LinkedHashSet<PsiType>();
-    for (TypeConstraint constraint : calculateTypeConstraints(element)) {
-      result.add(constraint.getDefaultType());
-    }
-    return result;
+  public static List<PsiType> getDefaultExpectedTypes(@NotNull GrExpression element) {
+    TypeConstraint[] constraints = calculateTypeConstraints(element);
+    return ContainerUtil.map(constraints, new Function<TypeConstraint, PsiType>() {
+      @Override
+      public PsiType fun(TypeConstraint constraint) {
+        return constraint.getDefaultType();
+      }
+    });
   }
 
   private static class MyCalculator extends GroovyElementVisitor {
@@ -176,8 +180,8 @@
       final GrClosableBlock[] closureArgs = methodCall.getClosureArguments();
       if (ArrayUtil.contains(myExpression, closureArgs)) {
         final GrArgumentList argumentList = methodCall.getArgumentList();
-        final GrNamedArgument[] namedArgs = argumentList == null ? GrNamedArgument.EMPTY_ARRAY : argumentList.getNamedArguments();
-        final GrExpression[] expressionArgs = argumentList == null ? GrExpression.EMPTY_ARRAY : argumentList.getExpressionArguments();
+        final GrNamedArgument[] namedArgs = argumentList.getNamedArguments();
+        final GrExpression[] expressionArgs = argumentList.getExpressionArguments();
         final GroovyResolveResult[] callVariants = ResolveUtil.getCallVariants(myExpression);
         processCallVariants(methodCall, callVariants, namedArgs, expressionArgs, closureArgs);
       }
@@ -344,18 +348,32 @@
                                      @NotNull GrNamedArgument[] namedArguments,
                                      @NotNull GrExpression[] expressionArguments,
                                      @NotNull GrClosableBlock[] closureArguments) {
+
+      List<Pair<PsiParameter, PsiType>> expectedParams =
+        ResolveUtil.collectExpectedParamsByArg(place, variants, namedArguments, expressionArguments, closureArguments, myExpression);
+
+      collectExpectedTypeFromPossibleParams(expectedParams);
+    }
+
+    private void collectExpectedTypeFromPossibleParams(List<Pair<PsiParameter, PsiType>> expectedParams) {
       List<TypeConstraint> constraints = ContainerUtil.newArrayList();
-      for (GroovyResolveResult variant : variants) {
-        final Map<GrExpression, Pair<PsiParameter, PsiType>> map = GrClosureSignatureUtil.mapArgumentsToParameters(
-          variant, place, true, true, namedArguments, expressionArguments, closureArguments
-        );
-        addConstraintsFromMap(constraints, map);
+      for (Pair<PsiParameter, PsiType> pair : expectedParams) {
+        final PsiType type = pair.second;
+        if (type != null) {
+
+          constraints.add(SubtypeConstraint.create(type));
+
+          if (type instanceof PsiArrayType && pair.first.isVarArgs()) {
+            constraints.add(SubtypeConstraint.create(((PsiArrayType)type).getComponentType()));
+          }
+        }
       }
       if (!constraints.isEmpty()) {
         myResult = constraints.toArray(new TypeConstraint[constraints.size()]);
       }
     }
 
+
     @Override
     public void visitBinaryExpression(GrBinaryExpression expression) {
       final IElementType type = expression.getOperationTokenType();
@@ -382,7 +400,8 @@
         }
       }
       else { //myExpression == right
-        processCallVariants(expression,  callVariants, GrNamedArgument.EMPTY_ARRAY, new GrExpression[]{myExpression}, GrClosableBlock.EMPTY_ARRAY);
+        processCallVariants(expression, callVariants, GrNamedArgument.EMPTY_ARRAY, new GrExpression[]{myExpression},
+                            GrClosableBlock.EMPTY_ARRAY);
       }
     }
 
@@ -398,22 +417,6 @@
       }
     }
 
-    private void addConstraintsFromMap(List<TypeConstraint> constraints, Map<GrExpression, Pair<PsiParameter, PsiType>> map) {
-      if (map == null) return;
-
-      final Pair<PsiParameter, PsiType> pair = map.get(myExpression);
-      if (pair == null) return;
-
-      final PsiType type = pair.second;
-      if (type == null) return;
-
-      constraints.add(SubtypeConstraint.create(type));
-
-      if (type instanceof PsiArrayType && pair.first.isVarArgs()) {
-        constraints.add(SubtypeConstraint.create(((PsiArrayType)type).getComponentType()));
-      }
-    }
-
     public void visitAssignmentExpression(GrAssignmentExpression expression) {
       GrExpression rValue = expression.getRValue();
       GrExpression lValue = expression.getLValue();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnnotationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnnotationUtil.java
index 387db84..b43ee28 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnnotationUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnnotationUtil.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.
@@ -15,11 +15,11 @@
  */
 package org.jetbrains.plugins.groovy.lang.psi.impl;
 
-import com.intellij.psi.PsiAnnotation;
-import com.intellij.psi.PsiAnnotationMemberValue;
-import com.intellij.psi.PsiLiteral;
+import com.intellij.psi.*;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
 
 /**
  * @author Max Medvedev
@@ -54,4 +54,52 @@
     }
     return null;
   }
+
+  @Nullable
+  public static PsiClass inferClassAttribute(@NotNull PsiAnnotation annotation, @NotNull String attributeName) {
+    final PsiAnnotationMemberValue targetValue = annotation.findAttributeValue(attributeName);
+    if (targetValue instanceof PsiClassObjectAccessExpression) {
+      PsiType type = ((PsiClassObjectAccessExpression)targetValue).getOperand().getType();
+      if (type instanceof PsiClassType) {
+        return ((PsiClassType)type).resolve();
+      }
+    }
+    else if (targetValue instanceof GrReferenceExpression) {
+      if ("class".equals(((GrReferenceExpression)targetValue).getReferenceName())) {
+        GrExpression qualifier = ((GrReferenceExpression)targetValue).getQualifier();
+        if (qualifier instanceof GrReferenceExpression) {
+          PsiElement resolved = ((GrReferenceExpression)qualifier).resolve();
+          if (resolved instanceof PsiClass) {
+            return (PsiClass)resolved;
+          }
+        }
+      }
+      PsiElement resolved = ((GrReferenceExpression)targetValue).resolve();
+      if (resolved instanceof PsiClass) return (PsiClass)resolved;
+    }
+    return null;
+  }
+
+  @Nullable
+  public static PsiType extractClassTypeFromClassAttributeValue(PsiAnnotationMemberValue targetValue) {
+    if (targetValue instanceof PsiClassObjectAccessExpression) {
+      return ((PsiClassObjectAccessExpression)targetValue).getOperand().getType();
+    }
+    else if (targetValue instanceof GrReferenceExpression) {
+      if ("class".equals(((GrReferenceExpression)targetValue).getReferenceName())) {
+        GrExpression qualifier = ((GrReferenceExpression)targetValue).getQualifier();
+        if (qualifier instanceof GrReferenceExpression) {
+          PsiElement resolved = ((GrReferenceExpression)qualifier).resolve();
+          if (resolved instanceof PsiClass) {
+            return qualifier.getType();
+          }
+        }
+      }
+      PsiElement resolved = ((GrReferenceExpression)targetValue).resolve();
+      if (resolved instanceof PsiClass) {
+        return ((GrReferenceExpression)targetValue).getType();
+      }
+    }
+    return null;
+  }
 }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java
index e2efdad..efddced 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java
@@ -56,7 +56,7 @@
                         @NotNull GlobalSearchScope scope,
                         @NotNull JavaPsiFacade facade,
                         @NotNull GrSignature signature,
-                        @NotNull PsiType[] typeArgs) {
+                        @Nullable PsiType[] typeArgs) {
     super(level, scope, facade);
 
     mySignature = signature;
@@ -132,7 +132,7 @@
 
   @Override
   public boolean equalsToText(@NotNull @NonNls String text) {
-    return text != null && text.equals(GroovyCommonClassNames.GROOVY_LANG_CLOSURE);
+    return text.equals(GroovyCommonClassNames.GROOVY_LANG_CLOSURE);
   }
 
   @Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrFieldImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrFieldImpl.java
index 7e85203..50ccc23 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrFieldImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrFieldImpl.java
@@ -23,6 +23,9 @@
 import com.intellij.psi.presentation.java.JavaPresentationUtil;
 import com.intellij.psi.search.SearchScope;
 import com.intellij.psi.stubs.IStubElementType;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiModificationTracker;
 import com.intellij.ui.LayeredIcon;
 import com.intellij.util.Function;
 import com.intellij.util.IncorrectOperationException;
@@ -59,8 +62,6 @@
  * Date: 25.05.2007
  */
 public class GrFieldImpl extends GrVariableBaseImpl<GrFieldStub> implements GrField, StubBasedPsiElement<GrFieldStub> {
-  private volatile GrAccessorMethod mySetter;
-  private volatile GrAccessorMethod[] myGetters;
 
   public GrFieldImpl(@NotNull ASTNode node) {
     super(node);
@@ -188,24 +189,24 @@
   }
 
   public GrAccessorMethod getSetter() {
-    if (mySetter == null) {
-      mySetter = GrAccessorMethodImpl.createSetterMethod(this);
-    }
-    return mySetter;
-  }
-
-  public void clearCaches() {
-    mySetter = null;
-    myGetters = null;
+    return CachedValuesManager.getCachedValue(this, new CachedValueProvider<GrAccessorMethod>() {
+      @Nullable
+      @Override
+      public Result<GrAccessorMethod> compute() {
+        return Result.create(GrAccessorMethodImpl.createSetterMethod(GrFieldImpl.this), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
+      }
+    });
   }
 
   @NotNull
   public GrAccessorMethod[] getGetters() {
-    if (myGetters == null) {
-      myGetters = GrAccessorMethodImpl.createGetterMethods(this);
-    }
-
-    return myGetters;
+    return CachedValuesManager.getCachedValue(this, new CachedValueProvider<GrAccessorMethod[]>() {
+      @Nullable
+      @Override
+      public Result<GrAccessorMethod[]> compute() {
+        return Result.create(GrAccessorMethodImpl.createGetterMethods(GrFieldImpl.this), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
+      }
+    });
   }
 
   @NotNull
@@ -240,7 +241,8 @@
   }
 
   @Nullable
-  public Icon getIcon(int flags) {
+  @Override
+  protected Icon getElementIcon(@IconFlags int flags) {
     Icon superIcon = JetgroovyIcons.Groovy.Field;
     if (!isProperty()) return superIcon;
     LayeredIcon rowIcon = new LayeredIcon(2);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java
index 990876d..6e31223 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableDeclarationImpl.java
@@ -1,6 +1,6 @@
 
 /*
- * 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.
@@ -25,7 +25,6 @@
 import com.intellij.psi.stubs.EmptyStub;
 import com.intellij.psi.util.CachedValueProvider;
 import com.intellij.psi.util.CachedValuesManager;
-import com.intellij.psi.util.PsiModificationTracker;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -212,7 +211,7 @@
       @Nullable
       @Override
       public Result<PsiReference> compute() {
-        return Result.create(getReferenceInner(), PsiModificationTracker.MODIFICATION_COUNT);
+        return Result.create(getReferenceInner(), getContainingFile());
       }
     });
   }
@@ -226,20 +225,40 @@
     final GrVariable[] variables = getVariables();
     if (variables.length == 0) return null;
 
-    final PsiElement resolved = variables[0];
-    return new PsiReferenceBase<GrVariableDeclaration>(this, range, true) {
-      @Nullable
-      @Override
-      public PsiElement resolve() {
-        return resolved;
-      }
+    final GrVariable resolved = variables[0];
+    final PsiType inferredType = resolved.getTypeGroovy();
+    if (inferredType == null) return null;
 
-      @NotNull
-      @Override
-      public Object[] getVariants() {
-        return EMPTY_ARRAY;
-      }
-    };
+    if (inferredType instanceof PsiClassType) {
+      return new PsiReferenceBase<GrVariableDeclaration>(this, range, true) {
+        @Nullable
+        @Override
+        public PsiElement resolve() {
+          return ((PsiClassType)inferredType).resolve();
+        }
+
+        @NotNull
+        @Override
+        public Object[] getVariants() {
+          return EMPTY_ARRAY;
+        }
+      };
+    }
+    else {
+      return new PsiReferenceBase<GrVariableDeclaration>(this, range, true) {
+        @Nullable
+        @Override
+        public PsiElement resolve() {
+          return resolved;
+        }
+
+        @NotNull
+        @Override
+        public Object[] getVariants() {
+          return EMPTY_ARRAY;
+        }
+      };
+    }
   }
 
   private TextRange getRangeForReference() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
index 3119608..825f4d8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
@@ -484,10 +484,11 @@
 
   @Override
   protected GrReferenceExpression bindWithQualifiedRef(@NotNull String qName) {
+    GrReferenceExpression qualifiedRef = GroovyPsiElementFactory.getInstance(getProject()).createReferenceExpressionFromText(qName);
     final GrTypeArgumentList list = getTypeArgumentList();
-    final String typeArgs = (list != null) ? list.getText() : "";
-    final String text = qName + typeArgs;
-    GrReferenceExpression qualifiedRef = GroovyPsiElementFactory.getInstance(getProject()).createReferenceExpressionFromText(text);
+    if (list != null) {
+      qualifiedRef.getNode().addChild(list.copy().getNode());
+    }
     getNode().getTreeParent().replaceChild(getNode(), qualifiedRef.getNode());
     return qualifiedRef;
   }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionBodyBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionBodyBase.java
index ea18c1b..1c9bdc9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionBodyBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionBodyBase.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.
@@ -22,6 +22,7 @@
 import com.intellij.psi.stubs.EmptyStub;
 import com.intellij.psi.stubs.IStubElementType;
 import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
@@ -39,15 +40,12 @@
 import org.jetbrains.plugins.groovy.lang.psi.impl.GrStubElementBase;
 import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
  * @author: Dmitry.Krasilschikov, ilyas
  */
 public abstract class GrTypeDefinitionBodyBase extends GrStubElementBase<EmptyStub> implements GrTypeDefinitionBody {
-  private GrField[] myFields = null;
-
   public GrTypeDefinitionBodyBase(@NotNull ASTNode node) {
     super(node);
   }
@@ -61,14 +59,6 @@
     return getParentByStub();
   }
 
-  public void subtreeChanged() {
-    super.subtreeChanged();
-    myFields = null;
-    for (GrField field : getFields()) {
-      field.clearCaches();
-    }
-  }
-
   public abstract void accept(GroovyElementVisitor visitor);
 
   public String toString() {
@@ -76,22 +66,18 @@
   }
 
   public GrField[] getFields() {
-    if (myFields == null) {
-      GrVariableDeclaration[] declarations = getStubOrPsiChildren(GroovyElementTypes.VARIABLE_DEFINITION, GrVariableDeclaration.ARRAY_FACTORY);
-      if (declarations.length == 0) return GrField.EMPTY_ARRAY;
-      List<GrField> result = new ArrayList<GrField>();
-      for (GrVariableDeclaration declaration : declarations) {
-        GrVariable[] variables = declaration.getVariables();
-        for (GrVariable variable : variables) {
-          if (variable instanceof GrField) {
-            result.add((GrField) variable);
-          }
+    GrVariableDeclaration[] declarations = getStubOrPsiChildren(GroovyElementTypes.VARIABLE_DEFINITION, GrVariableDeclaration.ARRAY_FACTORY);
+    List<GrField> result = ContainerUtil.newArrayList();
+    for (GrVariableDeclaration declaration : declarations) {
+      GrVariable[] variables = declaration.getVariables();
+      for (GrVariable variable : variables) {
+        if (variable instanceof GrField) {
+          result.add((GrField)variable);
         }
       }
-      myFields = result.toArray(new GrField[result.size()]);
     }
 
-    return myFields;
+    return result.toArray(new GrField[result.size()]);
   }
 
   public GrMethod[] getMethods() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java
index 0298021..1c20805 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.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.
@@ -19,10 +19,7 @@
 import com.intellij.lang.ASTNode;
 import com.intellij.navigation.ItemPresentation;
 import com.intellij.navigation.ItemPresentationProviders;
-import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.RecursionGuard;
-import com.intellij.openapi.util.RecursionManager;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleSettings;
@@ -31,7 +28,6 @@
 import com.intellij.psi.impl.source.tree.LeafPsiElement;
 import com.intellij.psi.scope.PsiScopeProcessor;
 import com.intellij.psi.stubs.IStubElementType;
-import com.intellij.psi.util.CachedValue;
 import com.intellij.psi.util.CachedValueProvider;
 import com.intellij.psi.util.CachedValuesManager;
 import com.intellij.psi.util.PsiModificationTracker;
@@ -40,7 +36,6 @@
 import com.intellij.util.ArrayUtilRt;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.VisibilityIcons;
-import com.intellij.util.containers.ContainerUtil;
 import icons.JetgroovyIcons;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -74,32 +69,21 @@
 import org.jetbrains.plugins.groovy.lang.psi.stubs.GrTypeDefinitionStub;
 import org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil;
 import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
-import org.jetbrains.plugins.groovy.lang.resolve.ast.AstTransformContributor;
 import org.jetbrains.plugins.groovy.runner.GroovyRunnerUtil;
-import org.jetbrains.plugins.groovy.util.LightCacheKey;
 
 import javax.swing.*;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 
-import static org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil.*;
+import static org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil.isClassEquivalentTo;
 
 /**
  * @author ilyas
  */
 public abstract class GrTypeDefinitionImpl extends GrStubElementBase<GrTypeDefinitionStub> implements GrTypeDefinition, StubBasedPsiElement<GrTypeDefinitionStub> {
 
-  private static final LightCacheKey<List<GrField>> AST_TRANSFORM_FIELD = LightCacheKey.createByJavaModificationCount();
-  private static final RecursionGuard ourGuard = RecursionManager.createGuard("groovyMembers");
-
-  private volatile PsiClass[] myInnerClasses;
-  private volatile GrMethod[] myGroovyMethods;
-  private volatile PsiMethod[] myConstructors;
-  private volatile GrMethod[] myCodeConstructors;
-
-  Key<CachedValue<PsiMethod[]>> CACHED_METHODS = Key.create("cached.type.definition.methods");
+  private final GrTypeDefinitionMembersCache myCache = new GrTypeDefinitionMembersCache(this);
 
   public GrTypeDefinitionImpl(@NotNull ASTNode node) {
     super(node);
@@ -331,150 +315,45 @@
     return GrClassImplUtil.findFieldByName(this, name, checkBases, false);
   }
 
-  private List<GrField> getSyntheticFields() {
-    List<GrField> fields = AST_TRANSFORM_FIELD.getCachedValue(this);
-    if (fields == null) {
-      final RecursionGuard.StackStamp stamp = ourGuard.markStack();
-      fields = AstTransformContributor.runContributorsForFields(this);
-      if (stamp.mayCacheNow()) {
-        fields = AST_TRANSFORM_FIELD.putCachedValue(this, fields);
-      }
-    }
-
-    return fields;
-  }
-
   @NotNull
   public GrField[] getFields() {
-    GrField[] codeFields = getCodeFields();
-
-    List<GrField> fromAstTransform = getSyntheticFields();
-    if (fromAstTransform.isEmpty()) return codeFields;
-
-    GrField[] res = new GrField[codeFields.length + fromAstTransform.size()];
-    System.arraycopy(codeFields, 0, res, 0, codeFields.length);
-
-    for (int i = 0; i < fromAstTransform.size(); i++) {
-      res[codeFields.length + i] = fromAstTransform.get(i);
-    }
-
-    return res;
+    return myCache.getFields();
   }
 
   @NotNull
   public PsiMethod[] getMethods() {
-    CachedValue<PsiMethod[]> cached = getUserData(CACHED_METHODS);
-    if (cached == null) {
-      cached = CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider<PsiMethod[]>() {
-        @Override
-        public Result<PsiMethod[]> compute() {
-          GrTypeDefinitionBody body = getBody();
-          List<PsiMethod> result = new ArrayList<PsiMethod>();
-          if (body != null) {
-            collectMethodsFromBody(body, result);
-          }
-
-          for (PsiMethod method : AstTransformContributor.runContributorsForMethods(GrTypeDefinitionImpl.this)) {
-            addExpandingReflectedMethods(result, method);
-          }
-
-          for (GrField field : getSyntheticFields()) {
-            ContainerUtil.addIfNotNull(result, field.getSetter());
-            Collections.addAll(result, field.getGetters());
-          }
-          return Result.create(result.toArray(new PsiMethod[result.size()]), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
-        }
-      }, false);
-      putUserData(CACHED_METHODS, cached);
-    }
-
-
-    return cached.getValue();
+    return myCache.getMethods();
   }
 
   @NotNull
   public GrMethod[] getCodeMethods() {
-    GrMethod[] cached = myGroovyMethods;
-    if (cached == null) {
-      RecursionGuard.StackStamp stamp = ourGuard.markStack();
-      GrTypeDefinitionBody body = getBody();
-      cached = body != null ? body.getMethods() : GrMethod.EMPTY_ARRAY;
-      if (stamp.mayCacheNow()) {
-        myGroovyMethods = cached;
-      }
-    }
-    return cached;
+    return myCache.getCodeMethods();
   }
 
   public void subtreeChanged() {
-    myInnerClasses = null;
-    myConstructors = null;
-    myCodeConstructors = null;
-    myGroovyMethods = null;
+    myCache.dropCaches();
     super.subtreeChanged();
   }
 
   @NotNull
   public PsiMethod[] getConstructors() {
-    PsiMethod[] cached = myConstructors;
-    if (cached == null) {
-      RecursionGuard.StackStamp stamp = ourGuard.markStack();
-      List<PsiMethod> result = new ArrayList<PsiMethod>();
-      for (final PsiMethod method : getMethods()) {
-        if (method.isConstructor()) {
-          addExpandingReflectedMethods(result, method);
-        }
-      }
-
-      cached = result.toArray(new PsiMethod[result.size()]);
-      if (stamp.mayCacheNow()) {
-        myConstructors = cached;
-      }
-    }
-    return cached;
+    return myCache.getConstructors();
   }
 
   @NotNull
   public GrMethod[] getCodeConstructors() {
-    GrMethod[] cached = myCodeConstructors;
-    if (cached == null) {
-      RecursionGuard.StackStamp stamp = ourGuard.markStack();
-      List<GrMethod> result = new ArrayList<GrMethod>();
-      for (final GrMethod method : getCodeMethods()) {
-        if (method.isConstructor()) {
-          result.add(method);
-        }
-      }
-
-      cached = result.toArray(new GrMethod[result.size()]);
-      if (stamp.mayCacheNow()) {
-        myCodeConstructors = cached;
-      }
-    }
-    return cached;
+    return myCache.getCodeConstructors();
   }
 
   @NotNull
   public PsiClass[] getInnerClasses() {
-    PsiClass[] inners = myInnerClasses;
-    if (inners == null) {
-      RecursionGuard.StackStamp stamp = ourGuard.markStack();
-      final GrTypeDefinitionBody body = getBody();
-      inners = body != null ? body.getInnerClasses() : PsiClass.EMPTY_ARRAY;
-      if (stamp.mayCacheNow()) {
-        myInnerClasses = inners;
-      }
-    }
-
-    return inners;
+    return myCache.getInnerClasses();
   }
 
   @NotNull
   public GrClassInitializer[] getInitializers() {
     GrTypeDefinitionBody body = getBody();
-    if (body == null) return GrClassInitializer.EMPTY_ARRAY;
-
-    return body.getInitializers();
+    return body != null ? body.getInitializers() : GrClassInitializer.EMPTY_ARRAY;
   }
 
   @NotNull
@@ -680,7 +559,8 @@
   }
 
   @Nullable
-  public Icon getIcon(int flags) {
+  @Override
+  protected Icon getElementIcon(@IconFlags int flags) {
     Icon icon = getIconInner();
     final boolean isLocked = (flags & ICON_FLAG_READ_STATUS) != 0 && !isWritable();
     RowIcon rowIcon = createLayeredIcon(this, icon, ElementPresentationUtil.getFlags(this, isLocked) | getFlagsInner());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionMembersCache.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionMembersCache.java
new file mode 100644
index 0000000..3a2ec2c
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionMembersCache.java
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.ModificationTracker;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.resolve.ast.AstTransformContributor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static com.intellij.psi.util.PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT;
+import static org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil.addExpandingReflectedMethods;
+import static org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil.collectMethodsFromBody;
+
+/**
+ * Created by Max Medvedev on 03/03/14
+ */
+public class GrTypeDefinitionMembersCache {
+  private static final Condition<PsiMethod> CONSTRUCTOR_CONDITION = new Condition<PsiMethod>() {
+    @Override
+    public boolean value(PsiMethod method) {
+      return method.isConstructor();
+    }
+  };
+
+  private final MyModificationTracker myTreeChangeTracker = new MyModificationTracker();
+
+  private final GrTypeDefinition myDefinition;
+
+  public GrTypeDefinitionMembersCache(GrTypeDefinition definition) {
+    myDefinition = definition;
+  }
+
+
+  public GrMethod[] getCodeMethods() {
+    return CachedValuesManager.getCachedValue(myDefinition, new CachedValueProvider<GrMethod[]>() {
+      @Nullable
+      @Override
+      public Result<GrMethod[]> compute() {
+        GrTypeDefinitionBody body = myDefinition.getBody();
+        GrMethod[] methods = body != null ? body.getMethods() : GrMethod.EMPTY_ARRAY;
+        return Result.create(methods, myTreeChangeTracker);
+      }
+    });
+  }
+
+  public GrMethod[] getCodeConstructors() {
+    return CachedValuesManager.getCachedValue(myDefinition, new CachedValueProvider<GrMethod[]>() {
+      @Nullable
+      @Override
+      public Result<GrMethod[]> compute() {
+        GrTypeDefinitionBody body = myDefinition.getBody();
+        GrMethod[] methods;
+        if (body != null) {
+          List<GrMethod> result = ContainerUtil.findAll(body.getMethods(), CONSTRUCTOR_CONDITION);
+          methods = result.toArray(new GrMethod[result.size()]);
+        }
+        else {
+          methods = GrMethod.EMPTY_ARRAY;
+        }
+        return Result.create(methods, myTreeChangeTracker);
+      }
+    });
+  }
+
+  public PsiMethod[] getConstructors() {
+    return CachedValuesManager.getCachedValue(myDefinition, new CachedValueProvider<PsiMethod[]>() {
+      @Nullable
+      @Override
+      public Result<PsiMethod[]> compute() {
+        List<PsiMethod> result = ContainerUtil.findAll(myDefinition.getMethods(), CONSTRUCTOR_CONDITION);
+        return Result.create(result.toArray(new PsiMethod[result.size()]), myTreeChangeTracker, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
+      }
+    });
+  }
+
+
+  public PsiClass[] getInnerClasses() {
+    return CachedValuesManager.getCachedValue(myDefinition, new CachedValueProvider<PsiClass[]>() {
+      @Nullable
+      @Override
+      public Result<PsiClass[]> compute() {
+        final GrTypeDefinitionBody body = myDefinition.getBody();
+        PsiClass[] inners = body != null ? body.getInnerClasses() : PsiClass.EMPTY_ARRAY;
+        return Result.create(inners, myTreeChangeTracker);
+      }
+    });
+  }
+
+  public GrField[] getFields() {
+    return CachedValuesManager.getCachedValue(myDefinition, new CachedValueProvider<GrField[]>() {
+      @Nullable
+      @Override
+      public Result<GrField[]> compute() {
+        return Result.create(getFieldsImpl(), myTreeChangeTracker, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
+      }
+    });
+  }
+
+  private GrField[] getFieldsImpl() {
+    GrField[] codeFields = myDefinition.getCodeFields();
+
+    List<GrField> fromAstTransform = getSyntheticFields();
+    if (fromAstTransform.isEmpty()) return codeFields;
+
+    GrField[] res = new GrField[codeFields.length + fromAstTransform.size()];
+    System.arraycopy(codeFields, 0, res, 0, codeFields.length);
+
+    for (int i = 0; i < fromAstTransform.size(); i++) {
+      res[codeFields.length + i] = fromAstTransform.get(i);
+    }
+
+    return res;
+  }
+
+  private List<GrField> getSyntheticFields() {
+    return CachedValuesManager.getCachedValue(myDefinition, new CachedValueProvider<List<GrField>>() {
+      @Nullable
+      @Override
+      public Result<List<GrField>> compute() {
+        return Result.create(AstTransformContributor.runContributorsForFields(myDefinition), myTreeChangeTracker, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
+      }
+    });
+  }
+
+  public PsiMethod[] getMethods() {
+    return CachedValuesManager.getCachedValue(myDefinition, new CachedValueProvider<PsiMethod[]>() {
+      @Override
+      public Result<PsiMethod[]> compute() {
+        List<PsiMethod> result = new ArrayList<PsiMethod>();
+        collectMethodsFromBody(myDefinition, result);
+
+        for (PsiMethod method : AstTransformContributor.runContributorsForMethods(myDefinition)) {
+          addExpandingReflectedMethods(result, method);
+        }
+
+        for (GrField field : getSyntheticFields()) {
+          ContainerUtil.addIfNotNull(result, field.getSetter());
+          Collections.addAll(result, field.getGetters());
+        }
+        return Result.create(result.toArray(new PsiMethod[result.size()]), myTreeChangeTracker, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
+      }
+    });
+  }
+
+  public void dropCaches() {
+    myTreeChangeTracker.inc();
+  }
+
+  private static class MyModificationTracker implements ModificationTracker {
+    private long myCount = 0;
+
+    @Override
+    public long getModificationCount() {
+      return myCount;
+    }
+
+    public void inc() {
+      myCount++;
+    }
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java
index b608f29..4fa96fe 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java
@@ -297,8 +297,9 @@
     return true;
   }
 
+  @Nullable
   @Override
-  public Icon getIcon(int flags) {
+  protected Icon getElementIcon(@IconFlags int flags) {
     RowIcon baseIcon = ElementPresentationUtil.createLayeredIcon(JetgroovyIcons.Groovy.Method, this, false);
     return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon);
   }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightField.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightField.java
index 2ce5612..204f4ad 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightField.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightField.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -21,6 +21,9 @@
 import com.intellij.psi.PsiType;
 import com.intellij.psi.impl.ResolveScopeManager;
 import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiModificationTracker;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -42,11 +45,6 @@
  */
 public class GrLightField extends GrLightVariable implements GrField {
 
-  protected GrAccessorMethod mySetter;
-  protected GrAccessorMethod[] myGetters;
-
-  protected boolean mySetterInitialized = false;
-
   private final PsiClass myContainingClass;
 
   public GrLightField(@NotNull PsiClass containingClass,
@@ -96,24 +94,27 @@
     return PsiUtil.isProperty(this);
   }
 
+  @Nullable
   @Override
   public GrAccessorMethod getSetter() {
-    if (mySetterInitialized) return mySetter;
-
-    mySetter = GrAccessorMethodImpl.createSetterMethod(this);
-    mySetterInitialized = true;
-
-    return mySetter;
+    return CachedValuesManager.getCachedValue(this, new CachedValueProvider<GrAccessorMethod>() {
+      @Nullable
+      @Override
+      public Result<GrAccessorMethod> compute() {
+        return Result.create(GrAccessorMethodImpl.createSetterMethod(GrLightField.this), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
+      }
+    });
   }
-
   @NotNull
   @Override
   public GrAccessorMethod[] getGetters() {
-    if (myGetters == null) {
-      myGetters = GrAccessorMethodImpl.createGetterMethods(this);
-    }
-
-    return myGetters;
+    return CachedValuesManager.getCachedValue(this, new CachedValueProvider<GrAccessorMethod[]>() {
+      @Nullable
+      @Override
+      public Result<GrAccessorMethod[]> compute() {
+        return Result.create(GrAccessorMethodImpl.createGetterMethods(GrLightField.this), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
+      }
+    });
   }
 
   @NotNull
@@ -123,13 +124,6 @@
   }
 
   @Override
-  public void clearCaches() {
-    mySetterInitialized = false;
-    mySetter = null;
-    myGetters = null;
-  }
-
-  @Override
   public void setInitializerGroovy(GrExpression initializer) {
     throw new IncorrectOperationException("cannot set initializer to light field!");
   }
@@ -178,7 +172,6 @@
   @Override
   public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
     PsiElement res = super.setName(name);
-    clearCaches();
     return res;
   }
 
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrScriptField.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrScriptField.java
index 42f9a91..86f5bdb 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrScriptField.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrScriptField.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.
@@ -23,6 +23,7 @@
 import com.intellij.psi.util.CachedValuesManager;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
 import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
@@ -45,10 +46,6 @@
   private GrScriptField(@NotNull GrVariable original, @NotNull GroovyScriptClass scriptClass) {
     super(scriptClass, original.getName(), original.getType(), original);
 
-    mySetterInitialized = true;
-    mySetter = null;
-    myGetters = GrAccessorMethod.EMPTY_ARRAY;
-
     final GrLightModifierList modifierList = getModifierList();
     for (@PsiModifier.ModifierConstant String modifier : PsiModifier.MODIFIERS) {
       if (original.hasModifierProperty(modifier)) {
@@ -65,6 +62,17 @@
     }
   }
 
+  @Nullable
+  @Override
+  public GrAccessorMethod getSetter() {
+    return null;
+  }
+
+  @NotNull
+  @Override
+  public GrAccessorMethod[] getGetters() {
+    return GrAccessorMethod.EMPTY_ARRAY;
+  }
 
   @NotNull
   public static GrScriptField getScriptField(@NotNull final GrVariable original) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java
index 92a013c..5108e85 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.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.
@@ -158,7 +158,9 @@
   @NotNull
   public PsiClassType[] getExtendsListTypes() {
     final PsiClassType superClassFromDSL = GroovyDslFileIndex.pocessScriptSuperClasses(myFile);
-    return new PsiClassType[]{ superClassFromDSL != null ? superClassFromDSL : TypesUtil.createTypeByFQClassName(GroovyCommonClassNames.GROOVY_LANG_SCRIPT, this)};
+    PsiClassType superClass = superClassFromDSL != null ? superClassFromDSL
+                                                        : TypesUtil.createTypeByFQClassName(GroovyCommonClassNames.GROOVY_LANG_SCRIPT, this);
+    return new PsiClassType[]{superClass};
   }
 
   @NotNull
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java
index aa7ca4c..12e6e2c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java
@@ -91,10 +91,11 @@
 
   @Override
   protected GrCodeReferenceElement bindWithQualifiedRef(@NotNull String qName) {
-    final GrTypeArgumentList list = getTypeArgumentList();
-    final String typeArgs = (list != null) ? list.getText() : "";
-    final String text = qName + typeArgs;
-    final GrCodeReferenceElement qualifiedRef = GroovyPsiElementFactory.getInstance(getProject()).createTypeOrPackageReference(text);
+    final GrCodeReferenceElement qualifiedRef = GroovyPsiElementFactory.getInstance(getProject()).createTypeOrPackageReference(qName);
+    final PsiElement list = getTypeArgumentList();
+    if (list != null) {
+      qualifiedRef.getNode().addChild(list.copy().getNode());
+    }
     getNode().getTreeParent().replaceChild(getNode(), qualifiedRef.getNode());
     return qualifiedRef;
   }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureAsAnonymousParameterEnhancer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureAsAnonymousParameterEnhancer.java
index 165b5f7..4607533 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureAsAnonymousParameterEnhancer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureAsAnonymousParameterEnhancer.java
@@ -29,7 +29,7 @@
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
 
 import java.util.Iterator;
-import java.util.Set;
+import java.util.List;
 
 /**
  * @author Max Medvedev
@@ -39,14 +39,14 @@
   @Override
   protected PsiType getClosureParameterType(GrClosableBlock closure, int index) {
 
-    Set<PsiType> expectedTypes;
+    List<PsiType> expectedTypes;
 
     if (closure.getParent() instanceof GrSafeCastExpression) {
       GrSafeCastExpression safeCastExpression = (GrSafeCastExpression)closure.getParent();
       GrTypeElement typeElement = safeCastExpression.getCastTypeElement();
       if (typeElement != null) {
         PsiType castType = typeElement.getType();
-        expectedTypes = ContainerUtil.newHashSet(GroovyExpectedTypesProvider.getDefaultExpectedTypes(safeCastExpression));
+        expectedTypes = ContainerUtil.newArrayList(GroovyExpectedTypesProvider.getDefaultExpectedTypes(safeCastExpression));
         for (Iterator<PsiType> iterator = expectedTypes.iterator(); iterator.hasNext(); ) {
           if (!TypesUtil.isAssignable(iterator.next(), castType, closure)) {
             iterator.remove();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java
index 2e88f33..3bea053 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java
@@ -16,11 +16,9 @@
 package org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
 
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Pair;
 import com.intellij.psi.*;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.psi.util.MethodSignature;
 import com.intellij.psi.util.PsiUtil;
 import com.intellij.util.containers.hash.HashMap;
 import com.intellij.util.containers.hash.HashSet;
@@ -37,7 +35,6 @@
 import org.jetbrains.plugins.groovy.lang.psi.impl.GrRangeType;
 import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
 import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
-import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
 import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil;
 import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
@@ -133,17 +130,10 @@
       return null;
     }
 
-    PsiType fromSam = inferParameterTypeFromSAM((GrMethodCall)parent, closure, index);
-    if (fromSam != null) {
-      return fromSam;
-    }
-
     String methodName = findMethodName((GrMethodCall)parent);
 
     GrExpression expression = ((GrMethodCall)parent).getInvokedExpression();
     if (!(expression instanceof GrReferenceExpression)) return null;
-//    final PsiElement resolved = ((GrReferenceExpression)expression).resolve();
-//    if (!(resolved instanceof GrGdkMethod)) return null;
 
     GrExpression qualifier = ((GrReferenceExpression)expression).getQualifierExpression();
     if (qualifier == null) return null;
@@ -265,42 +255,6 @@
   }
 
   @Nullable
-  private static PsiType inferParameterTypeFromSAM(@NotNull GrMethodCall methodCall, @NotNull GrClosableBlock closure, int index) {
-    if (!ClosureToSamConverter.isSamConversionAllowed(methodCall)) return null;
-
-    GroovyResolveResult resolveResult = methodCall.advancedResolve();
-    PsiElement resolved = resolveResult.getElement();
-
-    if (!(resolved instanceof PsiMethod)) return null;
-
-
-
-    Map<GrExpression,Pair<PsiParameter,PsiType>> map = GrClosureSignatureUtil.mapArgumentsToParameters(resolveResult, methodCall, false, true,
-                                                                                                       methodCall.getNamedArguments(),
-                                                                                                       methodCall.getExpressionArguments(),
-                                                                                                       methodCall.getClosureArguments());
-    if (map == null) return null;
-
-    Pair<PsiParameter, PsiType> samParameter = map.get(closure);
-    assert samParameter != null;
-
-    PsiType samTypeSubstituted = samParameter.getSecond();
-    if (!(samTypeSubstituted instanceof PsiClassType)) return null;
-
-    MethodSignature samSignature = ClosureToSamConverter.findSAMSignature(samTypeSubstituted);
-    if (samSignature == null) return null;
-
-    PsiType[] parameterTypes = samSignature.getParameterTypes();
-
-    if (index >= parameterTypes.length) {
-      return null;
-    }
-
-    return parameterTypes[index];
-  }
-
-
-  @Nullable
   private static PsiType getEntryForMap(@Nullable PsiType map, @NotNull final Project project, @NotNull final GlobalSearchScope scope) {
     PsiType key = PsiUtil.substituteTypeParameter(map, CommonClassNames.JAVA_UTIL_MAP, 0, true);
     PsiType value = PsiUtil.substituteTypeParameter(map, CommonClassNames.JAVA_UTIL_MAP, 1, true);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParamsEnhancer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParamsEnhancer.java
new file mode 100644
index 0000000..d717630
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParamsEnhancer.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
+import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
+import org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtil;
+import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
+import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 27/02/14
+ */
+public class ClosureParamsEnhancer extends AbstractClosureParameterEnhancer {
+
+  @Nullable
+  @Override
+  protected PsiType getClosureParameterType(GrClosableBlock closure, int index) {
+    if (!GroovyConfigUtils.getInstance().isVersionAtLeast(closure, GroovyConfigUtils.GROOVY2_3)) return null;
+
+    final GrParameter[] parameters = closure.getAllParameters();
+    if (containsParametersWithDeclaredType(parameters)) {
+      return null;
+    }
+
+    List<PsiType[]> fittingSignatures = findFittingSignatures(closure);
+
+    if (fittingSignatures.size() == 1) {
+      PsiType[] expectedSignature = fittingSignatures.get(0);
+      return expectedSignature[index];
+    }
+
+    return null;
+  }
+
+  @NotNull
+  public static List<PsiType[]> findFittingSignatures(GrClosableBlock closure) {
+
+    final GrParameter[] parameters = closure.getAllParameters();
+
+    GrCall call = findCall(closure);
+    if (call == null) return Collections.emptyList();
+
+    GroovyResolveResult resolveResult = call.advancedResolve();
+    PsiElement element = resolveResult.getElement();
+
+    if (!(element instanceof PsiMethod)) {
+      return Collections.emptyList();
+    }
+
+    while (element instanceof PsiMirrorElement) {
+      element = ((PsiMirrorElement)element).getPrototype();
+    }
+
+    List<Pair<PsiParameter,PsiType>> params = ResolveUtil.collectExpectedParamsByArg(closure,
+                                                                                     new GroovyResolveResult[]{resolveResult},
+                                                                                     call.getNamedArguments(),
+                                                                                     call.getExpressionArguments(),
+                                                                                     call.getClosureArguments(), closure);
+    if (params.isEmpty()) return Collections.emptyList();
+
+    Pair<PsiParameter, PsiType> pair = params.get(0);
+
+    PsiParameter param = pair.getFirst();
+    PsiModifierList modifierList = param.getModifierList();
+    if (modifierList == null) return Collections.emptyList();
+
+    PsiAnnotation anno = modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_STC_CLOSURE_PARAMS);
+    if (anno == null) return Collections.emptyList();
+
+    PsiClass closureSignatureHint = GrAnnotationUtil.inferClassAttribute(anno, "value");
+    if (closureSignatureHint == null) return Collections.emptyList();
+
+    String qnameOfClosureSignatureHint = closureSignatureHint.getQualifiedName();
+    if (qnameOfClosureSignatureHint == null) return Collections.emptyList();
+
+    SignatureHintProcessor signatureHintProcessor = SignatureHintProcessor.getHintProcessor(qnameOfClosureSignatureHint);
+    if (signatureHintProcessor == null) return Collections.emptyList();
+
+    List<PsiType[]> expectedSignatures = signatureHintProcessor.inferExpectedSignatures((PsiMethod)element,
+                                                                                         resolveResult.getSubstitutor(),
+                                                                                         SignatureHintProcessor.buildOptions(anno));
+
+    return ContainerUtil.findAll(expectedSignatures, new Condition<PsiType[]>() {
+      @Override
+      public boolean value(PsiType[] types) {
+        return types.length == parameters.length;
+      }
+    });
+  }
+
+  private static boolean containsParametersWithDeclaredType(GrParameter[] parameters) {
+    return ContainerUtil.find(parameters, new Condition<GrParameter>() {
+      @Override
+      public boolean value(GrParameter parameter) {
+        return parameter.getDeclaredType() != null;
+      }
+    }) != null;
+  }
+
+  @Nullable
+  private static GrCall findCall(@NotNull GrClosableBlock closure) {
+    PsiElement parent = closure.getParent();
+    if (parent instanceof GrCall && ArrayUtil.contains(closure, ((GrCall)parent).getClosureArguments())) {
+      return (GrCall)parent;
+    }
+
+    if (parent instanceof GrArgumentList) {
+      PsiElement pparent = parent.getParent();
+      if (pparent instanceof GrCall) {
+        return (GrCall)pparent;
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FirstParamHintProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FirstParamHintProcessor.java
new file mode 100644
index 0000000..7fdc103
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FirstParamHintProcessor.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.psi.PsiArrayType;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiSubstitutor;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 28/02/14
+ */
+public class FirstParamHintProcessor extends ParamHintProcessor {
+  public FirstParamHintProcessor() {
+    super("groovy.transform.stc.FirstParam", 0, -1);
+  }
+
+  public static class FirstGeneric extends ParamHintProcessor {
+    public FirstGeneric() {
+      super("groovy.transform.stc.FirstParam.FirstGenericType", 0, 0);
+    }
+  }
+
+  public static class SecondGeneric extends ParamHintProcessor {
+    public SecondGeneric() {
+      super("groovy.transform.stc.FirstParam.SecondGenericType", 0, 1);
+    }
+  }
+
+  public static class ThirdGeneric extends ParamHintProcessor {
+    public ThirdGeneric() {
+      super("groovy.transform.stc.FirstParam.ThirdGenericType", 0, 2);
+    }
+  }
+
+  public static class Component extends SignatureHintProcessor {
+    @Override
+    public String getHintName() {
+      return "groovy.transform.stc.FirstParam.Component";
+    }
+
+    @NotNull
+    @Override
+    public List<PsiType[]> inferExpectedSignatures(@NotNull PsiMethod method,
+                                                   @NotNull PsiSubstitutor substitutor,
+                                                   @NotNull String[] options) {
+      List<PsiType[]> signatures = new FirstParamHintProcessor().inferExpectedSignatures(method, substitutor, options);
+      if (signatures.size() == 1) {
+        PsiType[] signature = signatures.get(0);
+        if (signature.length == 1) {
+          PsiType type = signature[0];
+          if (type instanceof PsiArrayType) {
+            return produceResult(((PsiArrayType)type).getComponentType());
+          }
+        }
+      }
+      return Collections.emptyList();
+    }
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FromAbstractTypeMethodsHintProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FromAbstractTypeMethodsHintProcessor.java
new file mode 100644
index 0000000..d1c666f
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FromAbstractTypeMethodsHintProcessor.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.util.MethodSignature;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 28/02/14
+ */
+public class FromAbstractTypeMethodsHintProcessor extends SignatureHintProcessor {
+  @Override
+  public String getHintName() {
+    return "groovy.transform.stc.FromAbstractTypeMethods";
+  }
+
+  @NotNull
+  @Override
+  public List<PsiType[]> inferExpectedSignatures(@NotNull PsiMethod method,
+                                                 @NotNull PsiSubstitutor substitutor,
+                                                 @NotNull String[] options) {
+    if (options.length != 1) return Collections.emptyList();
+
+    String qname = options[0];
+    PsiClass aClass = JavaPsiFacade.getInstance(method.getProject()).findClass(qname, method.getResolveScope());
+    if (aClass == null) return Collections.emptyList();
+
+    Collection<MethodSignature> abstractSignatures = OverrideImplementExploreUtil.getMethodSignaturesToImplement(aClass);
+    return ContainerUtil.map(abstractSignatures, new Function<MethodSignature, PsiType[]>() {
+      @Override
+      public PsiType[] fun(MethodSignature signature) {
+        return signature.getParameterTypes();
+      }
+    });
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FromStringHintProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FromStringHintProcessor.java
new file mode 100644
index 0000000..6ca36c5
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/FromStringHintProcessor.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiSubstitutor;
+import com.intellij.psi.PsiType;
+import com.intellij.util.Function;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 28/02/14
+ */
+public class FromStringHintProcessor extends SignatureHintProcessor {
+
+  @Override
+  public String getHintName() {
+    return "groovy.transform.stc.FromString";
+  }
+
+  @NotNull
+  @Override
+  public List<PsiType[]> inferExpectedSignatures(@NotNull final PsiMethod method,
+                                                 @NotNull final PsiSubstitutor substitutor,
+                                                 @NotNull String[] options) {
+    return ContainerUtil.map(options, new Function<String, PsiType[]>() {
+      @Override
+      public PsiType[] fun(String value) {
+          String[] params = value.split(",");
+          return ContainerUtil.map(params, new Function<String, PsiType>() {
+            @Override
+            public PsiType fun(String param) {
+              try {
+                PsiType original = JavaPsiFacade.getElementFactory(method.getProject()).createTypeFromText(param, method);
+                return substitutor.substitute(original);
+              }
+              catch (IncorrectOperationException e) {
+                //do nothing. Just don't throw an exception
+              }
+              return PsiType.NULL;
+            }
+          }, new PsiType[params.length]);
+      }
+    });
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/MapEntryOrKeyValueHintProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/MapEntryOrKeyValueHintProcessor.java
new file mode 100644
index 0000000..799d02a
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/MapEntryOrKeyValueHintProcessor.java
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtilRt;
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 28/02/14
+ */
+public class MapEntryOrKeyValueHintProcessor extends SignatureHintProcessor {
+  @Override
+  public String getHintName() {
+    return "groovy.transform.stc.MapEntryOrKeyValue";
+  }
+
+  @NotNull
+  @Override
+  public List<PsiType[]> inferExpectedSignatures(@NotNull PsiMethod method,
+                                                 @NotNull PsiSubstitutor substitutor,
+                                                 @NotNull String[] options) {
+    int argNum = extractArgNum(options);
+    boolean index = extractIndex(options);
+
+    PsiParameter[] parameters = method.getParameterList().getParameters();
+
+    if (argNum >= parameters.length) return ContainerUtil.emptyList();
+
+    PsiParameter parameter = parameters[argNum];
+    PsiType type = parameter.getType();
+    PsiType substituted = substitutor.substitute(type);
+
+    if (!InheritanceUtil.isInheritor(substituted, CommonClassNames.JAVA_UTIL_MAP)) return ContainerUtil.emptyList();
+
+    PsiType key = PsiUtil.substituteTypeParameter(substituted, CommonClassNames.JAVA_UTIL_MAP, 0, true);
+    PsiType value = PsiUtil.substituteTypeParameter(substituted, CommonClassNames.JAVA_UTIL_MAP, 1, true);
+
+    PsiClass mapEntry = JavaPsiFacade.getInstance(method.getProject()).findClass(CommonClassNames.JAVA_UTIL_MAP_ENTRY, method.getResolveScope());
+    if (mapEntry == null) return ContainerUtil.emptyList();
+
+    PsiClassType mapEntryType = JavaPsiFacade.getElementFactory(method.getProject()).createType(mapEntry, key, value);
+
+    PsiType[] keyValueSignature = index ? new PsiType[]{key, value, PsiType.INT} : new PsiType[]{key, value};
+    PsiType[] mapEntrySignature = index ? new PsiType[]{mapEntryType, PsiType.INT} : new PsiType[]{mapEntryType};
+
+    return ContainerUtil.newArrayList(keyValueSignature, mapEntrySignature);
+  }
+
+  private static int extractArgNum(String[] options) {
+
+
+    for (String value : options) {
+      Integer parsedValue = parseArgNum(value);
+      if (parsedValue != null) {
+        return parsedValue;
+      }
+    }
+
+    if (options.length == 1) {
+      return StringUtilRt.parseInt(options[0], 0);
+    }
+
+    return 0;
+  }
+
+  private static boolean extractIndex(String[] options) {
+    for (String value : options) {
+      Boolean parsedValue = parseIndex(value);
+      if (parsedValue != null) {
+        return parsedValue;
+      }
+    }
+
+    if (options.length == 1) {
+      return StringUtilRt.parseBoolean(options[0], false);
+    }
+
+    return false;
+  }
+
+  private static Boolean parseIndex(String value) {
+    Pair<String, String> pair = parseValue(value);
+    if (pair == null) return null;
+
+    Boolean parsedValue = StringUtilRt.parseBoolean(pair.getSecond(), false);
+    if ("index".equals(pair.getFirst())) {
+      return parsedValue;
+    }
+
+    return null;
+  }
+
+  private static Integer parseArgNum(String value) {
+    Pair<String, String> pair = parseValue(value);
+    if (pair == null) return null;
+
+    Integer parsedValue = StringUtilRt.parseInt(pair.getSecond(), 0);
+    if ("argNum".equals(pair.getFirst())) {
+      return parsedValue;
+    }
+
+    return null;
+  }
+
+  @Nullable
+  private static Pair<String, String> parseValue(String value) {
+    String[] splitted = value.split("=");
+
+    if (splitted.length == 2) {
+      return Pair.create(splitted[0].trim(), splitted[1].trim());
+    }
+
+    return null;
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ParamHintProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ParamHintProcessor.java
new file mode 100644
index 0000000..3c9ac95
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ParamHintProcessor.java
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.ContainerUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 28/02/14
+ */
+public abstract class ParamHintProcessor extends SignatureHintProcessor {
+  private final int myParam;
+  private final int myGeneric;
+  private final String myHint;
+
+  public ParamHintProcessor(String hint, int param, int generic) {
+    myHint = hint;
+    myParam = param;
+    myGeneric = generic;
+  }
+
+  @Override
+  public String getHintName() {
+    return myHint;
+  }
+
+  @NotNull
+  @Override
+  public List<PsiType[]> inferExpectedSignatures(@NotNull PsiMethod method,
+                                                 @NotNull PsiSubstitutor substitutor,
+                                                 @NotNull String[] options) {
+    PsiParameter[] parameters = method.getParameterList().getParameters();
+    if (myParam < parameters.length) {
+      PsiParameter parameter = parameters[myParam];
+      PsiType originalType = parameter.getType();
+
+      PsiType substituted = substitutor.substitute(originalType);
+
+      if (myGeneric == -1) {
+        return produceResult(substituted);
+      }
+      else {
+        if (substituted instanceof PsiClassType) {
+          PsiType[] typeParameters = ((PsiClassType)substituted).getParameters();
+          if (myGeneric < typeParameters.length) {
+            return produceResult(typeParameters[myGeneric]);
+          }
+          //if (substituted.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
+          //  return produceResult(TypesUtil.createType(CommonClassNames.JAVA_LANG_CHARACTER, method));
+          //}
+        }
+      }
+    }
+    return ContainerUtilRt.emptyList();
+  }
+
+  @NotNull
+  protected static ArrayList<PsiType[]> produceResult(@Nullable PsiType type) {
+    PsiType notNull = type != null ? type : PsiType.NULL;
+    PsiType[] signature = {notNull};
+    ArrayList<PsiType[]> result = ContainerUtil.newArrayList();
+    result.add(signature);
+    return result;
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/SecondParamHintProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/SecondParamHintProcessor.java
new file mode 100644
index 0000000..fbfa821
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/SecondParamHintProcessor.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.psi.PsiArrayType;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiSubstitutor;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 28/02/14
+ */
+public class SecondParamHintProcessor extends ParamHintProcessor {
+  public SecondParamHintProcessor() {
+    super("groovy.transform.stc.SecondParam", 1, -1);
+  }
+
+  public static class FirstGeneric extends ParamHintProcessor {
+    public FirstGeneric() {
+      super("groovy.transform.stc.SecondParam.FirstGenericType", 1, 0);
+    }
+  }
+
+  public static class SecondGeneric extends ParamHintProcessor {
+    public SecondGeneric() {
+      super("groovy.transform.stc.SecondParam.SecondGenericType", 1, 1);
+    }
+  }
+
+  public static class ThirdGeneric extends ParamHintProcessor {
+    public ThirdGeneric() {
+      super("groovy.transform.stc.SecondParam.ThirdGenericType", 1, 2);
+    }
+  }
+
+  public static class Component extends SignatureHintProcessor {
+    @Override
+    public String getHintName() {
+      return "groovy.transform.stc.SecondParam.Component";
+    }
+
+    @NotNull
+    @Override
+    public List<PsiType[]> inferExpectedSignatures(@NotNull PsiMethod method,
+                                                   @NotNull PsiSubstitutor substitutor,
+                                                   @NotNull String[] options) {
+      List<PsiType[]> signatures = new SecondParamHintProcessor().inferExpectedSignatures(method, substitutor, options);
+      if (signatures.size() == 1) {
+        PsiType[] signature = signatures.get(0);
+        if (signature.length == 1) {
+          PsiType type = signature[0];
+          if (type instanceof PsiArrayType) {
+            return produceResult(((PsiArrayType)type).getComponentType());
+          }
+        }
+      }
+      return Collections.emptyList();
+    }
+  }
+
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/SignatureHintProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/SignatureHintProcessor.java
new file mode 100644
index 0000000..44c8f2a
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/SignatureHintProcessor.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 28/02/14
+ */
+public abstract class SignatureHintProcessor {
+  private static final ExtensionPointName<SignatureHintProcessor> EP_NAME = ExtensionPointName.create("org.intellij.groovy.signatureHintProcessor");
+
+  static String[] buildOptions(PsiAnnotation anno) {
+    PsiAnnotationMemberValue options = anno.findAttributeValue("options");
+    if (options instanceof PsiLiteral) {
+      Object value = ((PsiLiteral)options).getValue();
+      if (value instanceof String) {
+        return new String[]{(String)value};
+      }
+    }
+    else if (options instanceof PsiArrayInitializerMemberValue) {
+      PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)options).getInitializers();
+      ArrayList<String> result = ContainerUtil.newArrayList();
+      for (PsiAnnotationMemberValue initializer : initializers) {
+        if (initializer instanceof PsiLiteral) {
+          Object value = ((PsiLiteral)initializer).getValue();
+          if (value instanceof String) {
+            result.add((String)value);
+          }
+        }
+      }
+
+      return ArrayUtil.toStringArray(result);
+    }
+
+    return ArrayUtil.EMPTY_STRING_ARRAY;
+  }
+
+  public abstract String getHintName();
+
+  @NotNull
+  public abstract List<PsiType[]> inferExpectedSignatures(@NotNull PsiMethod method,
+                                                          @NotNull PsiSubstitutor substitutor,
+                                                          @NotNull String[] options);
+
+  @Nullable
+  public static SignatureHintProcessor getHintProcessor(@NotNull String hint) {
+    for (SignatureHintProcessor processor : EP_NAME.getExtensions()) {
+      if (hint.equals(processor.getHintName())) {
+        return processor;
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/SimpleTypeHintProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/SimpleTypeHintProcessor.java
new file mode 100644
index 0000000..dc5fafe
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/SimpleTypeHintProcessor.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiSubstitutor;
+import com.intellij.psi.PsiType;
+import com.intellij.util.Function;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 28/02/14
+ */
+public class SimpleTypeHintProcessor extends SignatureHintProcessor {
+  @Override
+  public String getHintName() {
+    return "groovy.transform.stc.SimpleType";
+  }
+
+  @NotNull
+  @Override
+  public List<PsiType[]> inferExpectedSignatures(@NotNull final PsiMethod method,
+                                                 @NotNull PsiSubstitutor substitutor,
+                                                 @NotNull String[] options) {
+    return Collections.singletonList(ContainerUtil.map(options, new Function<String, PsiType>() {
+      @Override
+      public PsiType fun(String value) {
+        try {
+          PsiType type = JavaPsiFacade.getElementFactory(method.getProject()).createTypeFromText(value, method);
+          return DefaultGroovyMethods.asBoolean(type) ? type : PsiType.NULL;
+        }
+        catch (IncorrectOperationException e) {
+          return PsiType.NULL;
+        }
+      }
+    }, new PsiType[options.length]));
+  }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ThirdParamHintProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ThirdParamHintProcessor.java
new file mode 100644
index 0000000..89d9355
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ThirdParamHintProcessor.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.psi.PsiArrayType;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiSubstitutor;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by Max Medvedev on 28/02/14
+ */
+public class ThirdParamHintProcessor extends ParamHintProcessor {
+  public ThirdParamHintProcessor() {
+    super("groovy.transform.stc.ThirdParam", 2, -1);
+  }
+
+  public static class FirstGeneric extends ParamHintProcessor {
+    public FirstGeneric() {
+      super("groovy.transform.stc.ThirdParam.FirstGenericType", 2, 0);
+    }
+  }
+
+  public static class SecondGeneric extends ParamHintProcessor {
+    public SecondGeneric() {
+      super("groovy.transform.stc.ThirdParam.SecondGenericType", 2, 1);
+    }
+  }
+
+  public static class ThirdGeneric extends ParamHintProcessor {
+    public ThirdGeneric() {
+      super("groovy.transform.stc.ThirdParam.ThirdGenericType", 2, 2);
+    }
+  }
+
+  public static class Component extends SignatureHintProcessor {
+    @Override
+    public String getHintName() {
+      return "groovy.transform.stc.ThirdParam.Component";
+    }
+
+    @NotNull
+    @Override
+    public List<PsiType[]> inferExpectedSignatures(@NotNull PsiMethod method,
+                                                   @NotNull PsiSubstitutor substitutor,
+                                                   @NotNull String[] options) {
+      List<PsiType[]> signatures = new ThirdParamHintProcessor().inferExpectedSignatures(method, substitutor, options);
+      if (signatures.size() == 1) {
+        PsiType[] signature = signatures.get(0);
+        if (signature.length == 1) {
+          PsiType type = signature[0];
+          if (type instanceof PsiArrayType) {
+            return produceResult(((PsiArrayType)type).getComponentType());
+          }
+        }
+      }
+      return Collections.emptyList();
+    }
+  }
+
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java
index dc08b53..7549688 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.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.
@@ -617,7 +617,7 @@
 
   private static boolean shouldImplementDelegatedInterfaces(PsiAnnotation delegate) {
     final Boolean result = GrAnnotationUtil.inferBooleanAttribute(delegate, "interfaces");
-    return result != null ? result.booleanValue() : true;
+    return result == null || result.booleanValue();
   }
 
   public static void addExpandingReflectedMethods(List<PsiMethod> result, PsiMethod method) {
@@ -631,12 +631,12 @@
     result.add(method);
   }
 
-  public static void collectMethodsFromBody(@NotNull GrTypeDefinitionBody body, List<PsiMethod> result) {
-    for (GrMethod method : body.getMethods()) {
+  public static void collectMethodsFromBody(@NotNull GrTypeDefinition definition, List<PsiMethod> result) {
+    for (GrMethod method : definition.getCodeMethods()) {
       addExpandingReflectedMethods(result, method);
     }
 
-    for (GrField field : body.getFields()) {
+    for (GrField field : definition.getFields()) {
       if (!field.isProperty()) continue;
       ContainerUtil.addAll(result, field.getGetters());
       ContainerUtil.addIfNotNull(result, field.getSetter());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java
index cfd5a26..0cf1870 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.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.
@@ -68,7 +68,7 @@
   @NonNls public static final String GROOVY_LANG_DELEGATES_TO = "groovy.lang.DelegatesTo";
   @NonNls public static final String GROOVY_LANG_DELEGATES_TO_TARGET = "groovy.lang.DelegatesTo.Target";
   @NonNls public static final String GROOVY_TRANSFORM_COMPILE_DYNAMIC = "groovy.transform.CompileDynamic";
-
+  @NonNls public static final String GROOVY_TRANSFORM_STC_CLOSURE_PARAMS = "groovy.transform.stc.ClosureParams";
 
   public static final Set<String> GROOVY_EXTENSION_CLASSES = Collections.unmodifiableSet(ContainerUtil.newLinkedHashSet(
     "org.codehaus.groovy.runtime.DateGroovyMethods",
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java
index 98bd1d9..ad16d8d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java
@@ -48,6 +48,7 @@
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
@@ -916,6 +917,33 @@
     }
   }
 
+  @NotNull
+  public static List<Pair<PsiParameter, PsiType>> collectExpectedParamsByArg(@NotNull PsiElement place,
+                                                                             @NotNull GroovyResolveResult[] variants,
+                                                                             @NotNull GrNamedArgument[] namedArguments,
+                                                                             @NotNull GrExpression[] expressionArguments,
+                                                                             @NotNull GrClosableBlock[] closureArguments,
+                                                                             @NotNull GrExpression arg) {
+    List<Pair<PsiParameter, PsiType>> expectedParams = ContainerUtil.newArrayList();
+
+    for (GroovyResolveResult variant : variants) {
+      final Map<GrExpression, Pair<PsiParameter, PsiType>> map = GrClosureSignatureUtil.mapArgumentsToParameters(
+        variant, place, true, true, namedArguments, expressionArguments, closureArguments
+      );
+
+      if (map != null) {
+        final Pair<PsiParameter, PsiType> pair = map.get(arg);
+        ContainerUtil.addIfNotNull(expectedParams, pair);
+      }
+    }
+    return expectedParams;
+  }
+
+  @NotNull
+  public static List<Pair<PsiParameter, PsiType>> collectExpectedParamsByArg(@NotNull GrCall call, @NotNull GrExpression arg) {
+    return collectExpectedParamsByArg(arg, call.getCallVariants(arg), call.getNamedArguments(), call.getExpressionArguments(), call.getClosureArguments(), arg);
+  }
+
   private static class DuplicateVariablesProcessor extends PropertyResolverProcessor {
     private boolean myBorderPassed;
     private final boolean myHasVisibilityModifier;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java
index 2aa286e..edb458e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java
@@ -37,7 +37,6 @@
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrExtendsClause;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrImplementsClause;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
 import org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtil;
 import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
@@ -117,10 +116,7 @@
       final List<PsiMethod> methods;
       if (clazz instanceof GrTypeDefinition) {
         methods = new ArrayList<PsiMethod>();
-        final GrTypeDefinitionBody body = ((GrTypeDefinition)clazz).getBody();
-        if (body != null) {
-          GrClassImplUtil.collectMethodsFromBody(body, methods);
-        }
+        GrClassImplUtil.collectMethodsFromBody((GrTypeDefinition)clazz, methods);
       }
       else {
         methods = Arrays.asList(clazz.getMethods());
@@ -247,10 +243,7 @@
     final List<PsiMethod> methods;
     if (currentClass instanceof GrTypeDefinition) {
       methods = new ArrayList<PsiMethod>();
-      final GrTypeDefinitionBody body = ((GrTypeDefinition)currentClass).getBody();
-      if (body != null) {
-        GrClassImplUtil.collectMethodsFromBody(body, methods);
-      }
+      GrClassImplUtil.collectMethodsFromBody((GrTypeDefinition)currentClass, methods);
     }
     else {
       methods = Arrays.asList(currentClass.getMethods());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
index 10e93ac..e78cc08 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
@@ -730,7 +730,7 @@
     return candidate;
   }
 
-  public static void assertStatement(@NotNull PsiElement anchor, @NotNull PsiElement scope) {
+  public static void assertStatement(@Nullable PsiElement anchor, @NotNull PsiElement scope) {
     if (!(anchor instanceof GrStatement)) {
       LogMessageEx.error(LOG, "cannot find anchor for variable", scope.getText());
     }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java
index 9f1a984..165f0f5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterHandler.java
@@ -188,7 +188,10 @@
 
   private static boolean isInplace(@NotNull IntroduceParameterInfo info,
                                    @NotNull Editor editor) {
-    return findExpr(info) != null && GrIntroduceHandlerBase.isInplace(editor, info.getContext());
+    return findExpr(info) != null &&
+           info.getToReplaceIn() instanceof GrMethod &&
+           info.getToSearchFor() instanceof PsiMethod &&
+           GrIntroduceHandlerBase.isInplace(editor, info.getContext());
   }
 
   @Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/dynamicMembers/GrDynamicPropertyImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/util/dynamicMembers/GrDynamicPropertyImpl.java
index 1521684..ecd79e6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/dynamicMembers/GrDynamicPropertyImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/util/dynamicMembers/GrDynamicPropertyImpl.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.
@@ -202,11 +202,6 @@
   }
 
   @Override
-  public void clearCaches() {
-    myField.clearCaches();
-  }
-
-  @Override
   public void setInitializerGroovy(GrExpression initializer) {
     throw new IncorrectOperationException("cannot set initializer to dynamic property!");
   }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/FastGroovyTestSuite.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/FastGroovyTestSuite.java
index 11597e9..42404ba 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/FastGroovyTestSuite.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/FastGroovyTestSuite.java
@@ -19,7 +19,6 @@
 import com.intellij.TestCaseLoader;
 import junit.framework.Test;
 import junit.framework.TestSuite;
-import org.jetbrains.plugins.groovy.compiler.GppCompilerTest;
 import org.jetbrains.plugins.groovy.compiler.GroovyCompilerTest;
 import org.jetbrains.plugins.groovy.compiler.GroovyDebuggerTest;
 import org.jetbrains.plugins.groovy.lang.GroovyStressPerformanceTest;
@@ -46,8 +45,7 @@
   private static boolean isSlow(Class aClass) {
     return aClass.equals(GroovyDebuggerTest.class) ||
            aClass.equals(GroovyStressPerformanceTest.class) ||
-           aClass.getName().startsWith(GroovyCompilerTest.class.getName()) ||
-           aClass.getName().startsWith(GppCompilerTest.class.getName());
+           aClass.getName().startsWith(GroovyCompilerTest.class.getName());
   }
 
 }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy
deleted file mode 100644
index 316de96..0000000
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.jetbrains.plugins.groovy.compiler
-
-import com.intellij.compiler.CompilerConfiguration
-import com.intellij.compiler.CompilerConfigurationImpl
-import com.intellij.compiler.server.BuildManager
-import com.intellij.openapi.util.io.FileUtil
-import com.intellij.openapi.vfs.VfsUtil
-import com.intellij.testFramework.PsiTestUtil
-import org.jetbrains.plugins.groovy.util.TestUtils
-/**
- * @author peter
- */
-public abstract class GppCompilerTest extends GroovyCompilerTestCase {
-  String[] oldPatterns
-
-  @Override protected void setUp() {
-    super.setUp();
-    PsiTestUtil.addLibrary myFixture.module, "gpp", TestUtils.absoluteTestDataPath + "/realGroovypp/", "groovy-all-1.8.2.jar", "groovypp-all-0.9.0_1.8.2.jar"
-    CompilerConfigurationImpl conf = CompilerConfiguration.getInstance(project)
-    oldPatterns = conf.resourceFilePatterns
-    conf.addResourceFilePattern("!*.gpp")
-  }
-
-  @Override
-  protected void tearDown() {
-    CompilerConfigurationImpl conf = CompilerConfiguration.getInstance(project)
-    conf.removeResourceFilePatterns()
-    oldPatterns.each { conf.addResourceFilePattern(it) }
-    super.tearDown()
-  }
-
-  public void testRecompileDependentGroovyClasses() throws Exception {
-    def a = myFixture.addFileToProject("A.gpp", """
-class A {
-  void foo() {
-    print "239"
-  }
-}
-""")
-    myFixture.addFileToProject("b.gpp", """
-new A().foo()
-""")
-    assertEmpty make()
-    assertOutput "b", "239"
-
-    VfsUtil.saveText a.virtualFile, """
-class A {
-  def foo() {
-    print "239"
-  }
-}
-"""
-
-    assertEmpty make()
-    assertOutput "b", "239"
-  }
-  
-  public void testRecompileDependentJavaClasses() throws Exception {
-    def a = myFixture.addFileToProject("A.gpp", """
-class A {
-  void foo() {
-    print "239"
-  }
-}
-""")
-    myFixture.addFileToProject("B.java", """
-public class B {
-  public static void main(String[] args) {
-    new A().foo();
-  }
-}
-""")
-    assertEmpty make()
-    assertOutput "B", "239"
-
-    VfsUtil.saveText a.virtualFile, """
-class A {
-  def foo() {
-    print "239"
-  }
-}
-"""
-
-    assertEmpty make()
-    assertOutput "B", "239"
-  }
-
-  public static class IdeaModeTest extends GppCompilerTest {
-    @Override
-    protected boolean useJps() { false }
-  }
-
-  public static class JpsModeTest extends GppCompilerTest {
-    @Override
-    protected boolean useJps() { true }
-
-    @Override
-    void testRecompileDependentJavaClasses() {
-      super.testRecompileDependentJavaClasses()
-    }
-
-    @Override
-    void testRecompileDependentGroovyClasses() {
-      super.testRecompileDependentGroovyClasses()
-    }
-
-    @Override
-    protected void tearDown() {
-      File systemRoot = BuildManager.getInstance().getBuildSystemDirectory()
-      try {
-        super.tearDown()
-      }
-      finally {
-        FileUtil.delete(systemRoot);
-      }
-    }
-  }
-
-
-}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
index da3963e..9be76d2 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
@@ -17,9 +17,9 @@
 package org.jetbrains.plugins.groovy.compiler
 import com.intellij.compiler.CompilerConfiguration
 import com.intellij.compiler.CompilerConfigurationImpl
+import com.intellij.compiler.impl.TranslatingCompilerFilesMonitor
 import com.intellij.compiler.server.BuildManager
 import com.intellij.openapi.application.ApplicationManager
-import com.intellij.openapi.application.PathManager
 import com.intellij.openapi.compiler.CompilerMessage
 import com.intellij.openapi.compiler.CompilerMessageCategory
 import com.intellij.openapi.compiler.options.ExcludeEntryDescription
@@ -41,6 +41,12 @@
     addGroovyLibrary(myModule);
   }
 
+  @Override
+  protected void tearDown() throws Exception {
+    TranslatingCompilerFilesMonitor.ourDebugMode = false
+    super.tearDown()
+  }
+
   public void testPlainGroovy() throws Throwable {
     myFixture.addFileToProject("A.groovy", "println '239'");
     assertEmpty(make());
@@ -128,6 +134,8 @@
   }
 
   public void testTransitiveJavaDependencyThroughGroovy() throws Throwable {
+    TranslatingCompilerFilesMonitor.ourDebugMode = true
+
     myFixture.addClass("public class IFoo { void foo() {} }").getContainingFile().getVirtualFile();
     myFixture.addFileToProject("Foo.groovy", "class Foo {\n" +
                                              "  static IFoo f\n" +
@@ -208,7 +216,7 @@
 
   @Override
   void runBare() {
-    new File(PathManager.systemPath, "compile-server/server.log").delete()
+    new File(TestLoggerFactory.testLogDir, "../log/build-log/build.log").delete()
     super.runBare()
   }
 
@@ -231,7 +239,7 @@
       def logText = ideaLog.text
       println(logText.size() < limit ? logText : logText.substring(logText.size() - limit))
     }
-    def makeLog = new File(PathManager.systemPath, "compile-server/server.log")
+    def makeLog = new File(TestLoggerFactory.testLogDir, "../log/build-log/build.log")
     if (makeLog.exists()) {
       println "\n\nServer Log:"
       println makeLog.text
@@ -725,11 +733,11 @@
     ApplicationManager.application.runWriteAction { msg.virtualFile.delete(this) }
 
     def messages = make()
-    assert messages 
+    assert messages
     def error = messages.find { it.message.contains('InvalidType') }
     assert error?.virtualFile
     assert groovyFile.classes[0] == GroovycStubGenerator.findClassByStub(project, error.virtualFile)
-    
+
   }
 
   public void "test ignore groovy internal non-existent interface helper inner class"() {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/Gr2_3HighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/Gr2_3HighlightingTest.groovy
new file mode 100644
index 0000000..273eb8f
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/Gr2_3HighlightingTest.groovy
@@ -0,0 +1,275 @@
+/*
+ * 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.
+ * 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 org.jetbrains.plugins.groovy.lang.highlighting
+
+import com.intellij.codeInspection.InspectionProfileEntry
+import com.intellij.testFramework.LightProjectDescriptor
+import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
+import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection
+import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection
+
+/**
+ * Created by Max Medvedev on 27/02/14
+ */
+class Gr2_3HighlightingTest extends GrHighlightingTestBase {
+  @Override
+  protected LightProjectDescriptor getProjectDescriptor() {
+    return GroovyLightProjectDescriptor.GROOVY_2_3
+  }
+
+  @Override
+  InspectionProfileEntry[] getCustomInspections() {
+    [new GroovyAssignabilityCheckInspection(), new GrUnresolvedAccessInspection()]
+  }
+
+  void assertScript(String text) {
+    testHighlighting("import groovy.transform.CompileStatic\nimport groovy.transform.stc.ClosureParams\n" + text)
+  }
+
+  void shouldFailWithMessages(String text) {
+    assertScript(text)
+  }
+
+  void testInferenceOnNonExtensionMethod() {
+    assertScript '''
+import groovy.transform.stc.FirstParam
+
+public <T> T foo(T arg, @ClosureParams(FirstParam) Closure c) { c.call(arg) }
+
+@CompileStatic
+def test() {
+    assert foo('a') { it.toUpperCase() } == 'A'
+}
+'''
+  }
+
+  void testFromStringWithSimpleType() {
+    assertScript '''
+import groovy.transform.stc.FromString
+
+void foo(@ClosureParams(value=FromString,options="java.lang.String") Closure cl) { cl.call('foo') }
+
+@CompileStatic
+def test() {
+    foo { String str -> println str.toUpperCase()}
+}
+'''
+
+    shouldFailWithMessages '''
+import groovy.transform.stc.FromString
+
+void foo(@ClosureParams(value=FromString,options="java.lang.String") Closure cl) { cl.call('foo') }
+
+@CompileStatic
+def test() {
+    foo { <error descr="Expected String">Date</error> str -> println str}
+}
+'''
+  }
+
+  void testFromStringWithGenericType() {
+    assertScript '''
+import groovy.transform.stc.FromString
+
+void foo(@ClosureParams(value=FromString,options="java.util.List<java.lang.String>") Closure cl) { cl.call(['foo']) }
+
+@CompileStatic
+def test() {
+    foo { List<String> str -> str.each { println it.toUpperCase() } }
+}
+'''
+
+    shouldFailWithMessages '''
+import groovy.transform.stc.FromString
+
+void foo(@ClosureParams(value=FromString,options="java.util.List<java.lang.String>") Closure cl) { cl.call(['foo']) }
+
+@CompileStatic
+def test() {
+    foo { <error descr="Expected List<String>">List<Date></error> d -> d.each { println it } }
+}
+'''
+  }
+
+  void testFromStringWithDirectGenericPlaceholder() {
+
+    assertScript '''
+import groovy.transform.stc.FromString
+
+public <T> void foo(T t, @ClosureParams(value=FromString,options="T") Closure cl) { cl.call(t) }
+
+@CompileStatic
+def test() {
+    foo('hey') { println it.toUpperCase() }
+}
+'''
+
+  }
+
+  void testFromStringWithGenericPlaceholder() {
+    assertScript '''
+import groovy.transform.stc.FromString
+
+public <T> void foo(T t, @ClosureParams(value=FromString,options="java.util.List<T>") Closure cl) { cl.call([t,t]) }
+
+@CompileStatic
+def test() {
+    foo('hey') { List<String> str -> str.each { println it.toUpperCase() } }
+}
+'''
+
+  }
+
+  void testFromStringWithGenericPlaceholderFromClass() {
+    assertScript '''
+import groovy.transform.stc.FromString
+
+class Foo<T> {
+    public void foo(@ClosureParams(value=FromString,options="java.util.List<T>") Closure cl) { cl.call(['hey','ya']) }
+}
+
+@CompileStatic
+def test() {
+    def foo = new Foo<String>()
+
+    foo.foo { List<String> str -> str.each { println it.toUpperCase() } }
+}'''
+  }
+
+  void testFromStringWithGenericPlaceholderFromClassWithTwoGenerics() {
+    assertScript '''
+import groovy.transform.stc.FromString
+
+class Foo<T,U> {
+    public void foo(@ClosureParams(value=FromString,options="java.util.List<U>") Closure cl) { cl.call(['hey','ya']) }
+}
+
+@CompileStatic
+def test() {
+    def foo = new Foo<Integer,String>()
+
+    foo.foo { List<String> str -> str.each { println it.toUpperCase() } }
+}'''
+  }
+
+  void testFromStringWithGenericPlaceholderFromClassWithTwoGenericsAndNoExplicitSignature() {
+    assertScript '''
+import groovy.transform.stc.FromString
+
+class Foo<T,U> {
+    public void foo(@ClosureParams(value=FromString,options="java.util.List<U>") Closure cl) { cl.call(['hey','ya']) }
+}
+
+@CompileStatic
+def test() {
+    def foo = new Foo<Integer,String>()
+
+    foo.foo { it.each { println it.toUpperCase() } }
+}'''
+  }
+
+  void testFromStringWithGenericPlaceholderFromClassWithTwoGenericsAndNoExplicitSignatureAndNoFQN() {
+    assertScript '''
+import groovy.transform.stc.FromString
+
+class Foo<T,U> {
+    public void foo(@ClosureParams(value=FromString,options="List<U>") Closure cl) { cl.call(['hey','ya']) }
+}
+
+@CompileStatic
+def test() {
+    def foo = new Foo<Integer,String>()
+
+    foo.foo { it.each { println it.toUpperCase() } }
+}'''
+  }
+
+  void testFromStringWithGenericPlaceholderFromClassWithTwoGenericsAndNoExplicitSignatureAndNoFQNAndReferenceToSameUnitClass() {
+    assertScript '''
+import groovy.transform.stc.FromString
+
+class Foo {
+    void bar() {
+        println 'Haha!'
+    }
+}
+
+class Tor<D,U> {
+    public void foo(@ClosureParams(value=FromString,options="List<U>") Closure cl) { cl.call([new Foo(), new Foo()]) }
+}
+
+@CompileStatic
+def test() {
+    def tor = new Tor<Integer,Foo>()
+
+    tor.foo { it.each { it.bar() } }
+}'''
+  }
+
+  void testFromStringWithGenericPlaceholderFromClassWithTwoGenericsAndNoExplicitSignatureAndNoFQNAndReferenceToSameUnitClassAndTwoArgs() {
+    assertScript '''
+import groovy.transform.stc.FromString
+
+class Foo {
+    void bar() {
+        println 'Haha!'
+    }
+}
+
+class Tor<D,U> {
+    public void foo(@ClosureParams(value=FromString,options=["D,List<U>"]) Closure cl) { cl.call(3, [new Foo(), new Foo()]) }
+}
+
+@CompileStatic
+def test() {
+
+    def tor = new Tor<Integer,Foo>()
+
+    tor.foo { r, e -> r.times { e.each { it.bar() } } }
+}
+'''
+  }
+
+  void testFromStringWithGenericPlaceholderFromClassWithTwoGenericsAndPolymorphicSignature() {
+    assertScript '''
+import groovy.transform.stc.FromString
+
+class Foo {
+    void bar() {
+        println 'Haha!'
+    }
+}
+
+class Tor<D,U> {
+    public void foo(@ClosureParams(value=FromString,options=["D,List<U>", "D"]) Closure cl) {
+        if (cl.maximumNumberOfParameters==2) {
+            cl.call(3, [new Foo(), new Foo()])
+        } else {
+            cl.call(3)
+        }
+    }
+}
+
+@CompileStatic
+def test() {
+    def tor = new Tor<Integer,Foo>()
+
+    tor.foo { r, e -> r.times { e.each { it.bar() } } }
+    tor.foo { it.times { println 'polymorphic' } }
+}
+'''
+  }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy
index 2b9ecad..246c5ca 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrInspectionTest.groovy
@@ -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.
@@ -26,9 +26,9 @@
 import org.jetbrains.plugins.groovy.codeInspection.exception.GroovyEmptyCatchBlockInspection
 import org.jetbrains.plugins.groovy.codeInspection.metrics.GroovyOverlyLongMethodInspection
 import org.jetbrains.plugins.groovy.codeInspection.noReturnMethod.MissingReturnInspection
-import org.jetbrains.plugins.groovy.codeInspection.threading.GroovyUnconditionalWaitInspection
 import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection
 import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GroovyUntypedAccessInspection
+
 /**
  * @author Max Medvedev
  */
@@ -146,29 +146,6 @@
 ''', MissingReturnInspection)
   }
 
-  void testReassignedVarInClosureInspection() {
-    addCompileStatic()
-    testHighlighting("""\
-test() {
-    def var = "abc"
-    def cl = {
-        <warning descr="Local variable 'var' is reassigned">var</warning> = new Date()
-    }
-    cl()
-    var.toUpperCase()
-}
-
-test2() {
-    def var = "abc"
-    def cl = {
-        <warning descr="Local variable 'var' is reassigned">var</warning> = 'cde'
-    }
-    cl()
-    var.toUpperCase()
-}
-""", GrReassignedInClosureLocalVarInspection)
-  }
-
   void testPackageDefinition() {
     myFixture.addFileToProject('cde/bar.groovy', '//empty file')
     myFixture.addFileToProject('abc/foo.groovy', '''\
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/GroovyAddImportActionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/GroovyAddImportActionTest.groovy
index 54543f2..97fb5d1 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/GroovyAddImportActionTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/GroovyAddImportActionTest.groovy
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,9 +15,7 @@
  */
 
 package org.jetbrains.plugins.groovy.refactoring.optimizeImports
-
 import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
-import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection
 /**
  * @author peter
  */
@@ -27,20 +25,34 @@
     myFixture.addClass 'package foo; public class Log {}'
     myFixture.addClass 'package bar; public class Log {}'
     myFixture.addClass 'package bar; public class LogFactory { public static Log log(){} }'
-    myFixture.configureByText 'a.groovy', '''
+    doTest('''\
 public class Foo {
     Lo<caret>g l = bar.LogFactory.log();
 }
-'''
-    myFixture.enableInspections(new GrUnresolvedAccessInspection())
+''', '''\
+import bar.Log
 
+public class Foo {
+    Lo<caret>g l = bar.LogFactory.log();
+}
+''')
+  }
+
+  void testReferenceWithErrors() {
+    myFixture.addClass 'package foo; public class Abc<X, Y> {}'
+    doTest('''\
+A<caret>bc<String, > foo = null
+''', '''\
+import foo.Abc
+
+A<caret>bc<String, > foo = null
+''')
+  }
+
+  private void doTest(String before, String after) {
+    myFixture.configureByText 'a.groovy', before
     importClass()
-    myFixture.checkResult '''import bar.Log
-
-public class Foo {
-    Lo<caret>g l = bar.LogFactory.log();
-}
-'''
+    myFixture.checkResult after
   }
 
   private def importClass() {
diff --git a/plugins/groovy/testdata/mockGroovyLib2.3/groovy-all-2.3.0.jar b/plugins/groovy/testdata/mockGroovyLib2.3/groovy-all-2.3.0.jar
index 3b5173f..720d4a9 100644
--- a/plugins/groovy/testdata/mockGroovyLib2.3/groovy-all-2.3.0.jar
+++ b/plugins/groovy/testdata/mockGroovyLib2.3/groovy-all-2.3.0.jar
Binary files differ
diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
index 1531965..5f5a167 100644
--- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
+++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
@@ -132,3 +132,4 @@
 
 hg4idea.annotation.tool.tip=commit {0}\nAuthor: {1}\nDate: {2}\n\n{3}
 hg4idea.push.asNewBranch=push as &new remote branch
+hg4idea.push.bookmark=Book&mark
diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml
index ba40408..f0ce13c 100644
--- a/plugins/hg4idea/src/META-INF/plugin.xml
+++ b/plugins/hg4idea/src/META-INF/plugin.xml
@@ -1,7 +1,17 @@
 <idea-plugin>
   <id>hg4idea</id>
   <name>hg4idea</name>
-  <description>Provides integration with Mercurial version control system. Supports Mercurial 1.3+.</description>
+  <description>
+      <![CDATA[
+      Allows working with <a href="http://mercurial.selenic.com/">Mercurial version control system</a>.
+      The following features are available:
+        <ul>
+        <li>Dedicated page under the Version Control node in the Settings/Preferences dialog.</li>
+        <li>Ability to browse, check out sources from and import into the available Mercurial repositories, when Mercurial is not enabled.</li>
+        <li>When Mercurial is enabled, the Mercurial node appears on the VCS menu, and on the context menu of the editor.
+        </ul>
+      ]]>
+   </description>
   <category>VCS Integration</category>
   <version>10.0</version>
   <vendor email="victor.iacoban@gmail.com, willem.verstraeten@gmail.com" url="http://www.bitbucket.org/willemv/hg4idea">Victor Iacoban and Willem Verstraeten</vendor>
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java
index 9c10a51..17d4f36 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java
@@ -23,27 +23,21 @@
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.action.HgCommandResultNotifier;
 import org.zmlx.hg4idea.command.HgPushCommand;
-import org.zmlx.hg4idea.command.HgTagBranch;
-import org.zmlx.hg4idea.command.HgTagBranchCommand;
 import org.zmlx.hg4idea.execution.HgCommandResult;
 import org.zmlx.hg4idea.execution.HgCommandResultHandler;
+import org.zmlx.hg4idea.repo.HgRepository;
 import org.zmlx.hg4idea.ui.HgPushDialog;
-import org.zmlx.hg4idea.util.HgUtil;
 
-import java.util.Collections;
+import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-/**
- * @author Kirill Likhodedov
- */
 public class HgPusher {
 
   private static final Logger LOG = Logger.getInstance(HgPusher.class);
@@ -59,52 +53,27 @@
     myProject = project;
   }
 
-  public void showDialogAndPush(@Nullable final VirtualFile selectedRepo) {
-    HgUtil.executeOnPooledThreadIfNeeded(new Runnable() {
-      public void run() {
-        final List<VirtualFile> repositories = HgUtil.getHgRepositories(myProject);
-        if (repositories.isEmpty()) {
-          VcsBalloonProblemNotifier.showOverChangesView(myProject, "No Mercurial repositories in the project", MessageType.ERROR);
-          return;
-        }
-        VirtualFile firstRepo = repositories.get(0);
-        final List<HgTagBranch> branches = getBranches(myProject, firstRepo);
-        if (branches.isEmpty()) {
-          return;
-        }
-        final AtomicReference<HgPushCommand> pushCommand = new AtomicReference<HgPushCommand>();
-        UIUtil.invokeAndWaitIfNeeded(new Runnable() {
-          @Override
-          public void run() {
-            final HgPushDialog dialog = new HgPushDialog(myProject, repositories, branches, selectedRepo);
-            dialog.show();
-            if (dialog.isOK()) {
-              dialog.rememberSettings();
-              pushCommand.set(preparePushCommand(myProject, dialog));
-              new Task.Backgroundable(myProject, "Pushing...", false) {
-                @Override
-                public void run(@NotNull ProgressIndicator indicator) {
-                  if (pushCommand.get() != null) {
-                    push(myProject, pushCommand.get());
-                  }
-                }
-              }.queue();
-            }
-          }
-        });
-      }
-    });
-  }
+  public void showDialogAndPush (@NotNull Collection<HgRepository> repositories,@Nullable final HgRepository selectedRepo) {
 
-  @NotNull
-  public static List<HgTagBranch> getBranches(@NotNull Project project, @NotNull VirtualFile root) {
-    HgCommandResult branchesResult = new HgTagBranchCommand(project, root).collectBranches();
-    if (branchesResult == null) {
-      new HgCommandResultNotifier(project)
-        .notifyError(branchesResult, "Mercurial command failed", HgVcsMessages.message("hg4idea.branches.error.description"));
-      return Collections.emptyList();
+    if (repositories.isEmpty()) {
+      VcsBalloonProblemNotifier.showOverChangesView(myProject, "No Mercurial repositories in the project", MessageType.ERROR);
+      return;
     }
-    return HgTagBranchCommand.parseResult(branchesResult);
+    final AtomicReference<HgPushCommand> pushCommand = new AtomicReference<HgPushCommand>();
+    final HgPushDialog dialog = new HgPushDialog(myProject, repositories, selectedRepo);
+    dialog.show();
+    if (dialog.isOK()) {
+      dialog.rememberSettings();
+      pushCommand.set(preparePushCommand(myProject, dialog));
+      new Task.Backgroundable(myProject, "Pushing...", false) {
+        @Override
+        public void run(@NotNull ProgressIndicator indicator) {
+          if (pushCommand.get() != null) {
+            push(myProject, pushCommand.get());
+          }
+        }
+      }.queue();
+    }
   }
 
   private static void push(final Project project, HgPushCommand command) {
@@ -122,9 +91,11 @@
           String successDescription = String.format("Pushed %d %s [%s]", commitsNum, StringUtil.pluralize("commit", commitsNum),
                                                     repo.getPresentableName());
           new HgCommandResultNotifier(project).notifySuccess(successTitle, successDescription);
-        } else if (result.getExitValue() == NOTHING_TO_PUSH_EXIT_VALUE) {
+        }
+        else if (result.getExitValue() == NOTHING_TO_PUSH_EXIT_VALUE) {
           new HgCommandResultNotifier(project).notifySuccess("", "Nothing to push");
-        } else {
+        }
+        else {
           new HgCommandResultNotifier(project).notifyError(result, "Push failed",
                                                            "Failed to push to [" + repo.getPresentableName() + "]");
         }
@@ -133,10 +104,11 @@
   }
 
   private static HgPushCommand preparePushCommand(Project project, HgPushDialog dialog) {
-    final HgPushCommand command = new HgPushCommand(project, dialog.getRepository(), dialog.getTarget());
+    final HgPushCommand command = new HgPushCommand(project, dialog.getRepository().getRoot(), dialog.getTarget());
     command.setRevision(dialog.getRevision());
     command.setForce(dialog.isForce());
-    command.setBranch(dialog.getBranch());
+    command.setBranchName(dialog.getBranch());
+    command.setBookmarkName(dialog.getBookmarkName());
     command.setIsNewBranch(dialog.isNewBranch());
     return command;
   }
@@ -159,5 +131,4 @@
     }
     return numberOfCommitsInAllSubrepos;
   }
-
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
index 3db5f19..9984fac 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
@@ -23,6 +23,8 @@
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgVcs;
+import org.zmlx.hg4idea.repo.HgRepository;
+import org.zmlx.hg4idea.repo.HgRepositoryManager;
 import org.zmlx.hg4idea.util.HgUtil;
 
 import javax.swing.*;
@@ -47,10 +49,11 @@
       return;
     }
     VirtualFile file = event.getData(CommonDataKeys.VIRTUAL_FILE);
-    VirtualFile repo = file != null ? HgUtil.getHgRootOrNull(project, file) : null;
-    List<VirtualFile> repos = HgUtil.getHgRepositories(project);
-    if (!repos.isEmpty()) {
-      execute(project, repos, repo);
+    HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project);
+    HgRepository repo = file != null ? repositoryManager.getRepositoryForFile(file): HgUtil.getCurrentRepository(project);
+    List<HgRepository> repositories = repositoryManager.getRepositories();
+    if (!repositories.isEmpty()) {
+      execute(project, repositories, repo);
     }
   }
 
@@ -62,8 +65,8 @@
   }
 
   protected abstract void execute(@NotNull Project project,
-                                  @NotNull Collection<VirtualFile> repositories,
-                                  @Nullable VirtualFile selectedRepo);
+                                  @NotNull Collection<HgRepository> repositories,
+                                  @Nullable HgRepository selectedRepo);
 
   public static void handleException(@Nullable Project project, @NotNull Exception e) {
     handleException(project, "Error", e);
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java
deleted file mode 100644
index 6660d10..0000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2000-2011 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 org.zmlx.hg4idea.action;
-
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.util.HgUtil;
-
-import javax.swing.*;
-
-/**
- * @author Kirill Likhodedov
- */
-public abstract class HgAction extends AnAction {
-  protected HgAction() {
-  }
-
-  protected HgAction(Icon icon) {
-    super(icon);
-  }
-
-  @Override
-  public void actionPerformed(AnActionEvent event) {
-    final DataContext dataContext = event.getDataContext();
-    final Project project = CommonDataKeys.PROJECT.getData(dataContext);
-    if (project == null) {
-      return;
-    }
-    VirtualFile file = event.getData(CommonDataKeys.VIRTUAL_FILE);
-    VirtualFile repo = file != null ? HgUtil.getHgRootOrNull(project, file) : null;
-    execute(project, repo);
-  }
-
-  @Override
-  public void update(AnActionEvent e) {
-    boolean enabled = HgAbstractGlobalAction.isEnabled(e);
-    e.getPresentation().setEnabled(enabled);
-  }
-
-  public abstract void execute(Project project, @Nullable VirtualFile selectedRepo);
-
-}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchAbstractAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchAbstractAction.java
new file mode 100644
index 0000000..78b6701
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchAbstractAction.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ * 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 org.zmlx.hg4idea.action;
+
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.zmlx.hg4idea.repo.HgRepository;
+
+public abstract class HgBranchAbstractAction extends DumbAwareAction {
+  @NotNull protected final Project myProject;
+  @NotNull protected final HgRepository mySelectedRepository;
+  @NotNull protected final String myBranchName;
+
+  public HgBranchAbstractAction(@NotNull Project project, @NotNull String title,
+                                @NotNull HgRepository selectedRepository,
+                                @NotNull String branchName) {
+    super(title);
+    myProject = project;
+    mySelectedRepository = selectedRepository;
+    myBranchName = branchName;
+  }
+}
\ No newline at end of file
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java
index b2b4f99..0162724 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java
@@ -23,13 +23,10 @@
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.DefaultActionGroup;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vcs.update.UpdatedFiles;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ArrayUtil;
 import com.intellij.util.Function;
 import com.intellij.util.PlatformIcons;
 import com.intellij.util.containers.ContainerUtil;
@@ -39,14 +36,12 @@
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgNameWithHashInfo;
 import org.zmlx.hg4idea.HgRevisionNumber;
-import org.zmlx.hg4idea.HgVcs;
-import org.zmlx.hg4idea.HgVcsMessages;
-import org.zmlx.hg4idea.command.*;
+import org.zmlx.hg4idea.command.HgBookmarkCommand;
+import org.zmlx.hg4idea.command.HgBranchCreateCommand;
+import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand;
 import org.zmlx.hg4idea.execution.HgCommandException;
 import org.zmlx.hg4idea.execution.HgCommandResult;
 import org.zmlx.hg4idea.execution.HgCommandResultHandler;
-import org.zmlx.hg4idea.provider.update.HgConflictResolver;
-import org.zmlx.hg4idea.provider.update.HgHeadMerger;
 import org.zmlx.hg4idea.repo.HgRepository;
 import org.zmlx.hg4idea.ui.HgBookmarkDialog;
 import org.zmlx.hg4idea.util.HgErrorUtil;
@@ -55,9 +50,6 @@
 
 import static org.zmlx.hg4idea.util.HgUtil.*;
 
-/**
- * @author Nadya Zabrodina
- */
 public class HgBranchPopupActions {
 
   private final Project myProject;
@@ -80,9 +72,8 @@
     popupGroup.addSeparator("Bookmarks");
     List<String> bookmarkNames = getNamesWithoutHashes(myRepository.getBookmarks());
     String currentBookmark = myRepository.getCurrentBookmark();
-    Collections.sort(bookmarkNames);
     for (String bookmark : bookmarkNames) {
-      AnAction bookmarkAction = new BranchActions(myProject, bookmark, myRepository);
+      AnAction bookmarkAction = new BookmarkActions(myProject, myRepository, bookmark);
       if (bookmark.equals(currentBookmark)) {
         bookmarkAction.getTemplatePresentation().setIcon(PlatformIcons.CHECK_ICON);
       }
@@ -94,7 +85,7 @@
     Collections.sort(branchNamesList);
     for (String branch : branchNamesList) {
       if (!branch.equals(myRepository.getCurrentBranch())) { // don't show current branch in the list
-        popupGroup.add(new BranchActions(myProject, branch, myRepository));
+        popupGroup.add(new HgCommonBranchActions(myProject, myRepository, branch));
       }
     }
     return popupGroup;
@@ -160,17 +151,7 @@
       if (bookmarkDialog.isOK()) {
         try {
           final String name = bookmarkDialog.getName();
-          new HgBookmarkCreateCommand(myProject, myPreselectedRepo, name,
-                                      bookmarkDialog.isActive()).execute(new HgCommandResultHandler() {
-            @Override
-            public void process(@Nullable HgCommandResult result) {
-              getRepositoryManager(myProject).updateRepository(myPreselectedRepo);
-              if (HgErrorUtil.hasErrorsInCommandExecution(result)) {
-                new HgCommandResultNotifier(myProject)
-                  .notifyError(result, "Creation failed", "Bookmark creation [" + name + "] failed");
-              }
-            }
-          });
+          new HgBookmarkCommand(myProject, myPreselectedRepo, name).createBookmark(bookmarkDialog.isActive());
         }
         catch (HgCommandException exception) {
           HgAbstractGlobalAction.handleException(myProject, exception);
@@ -229,7 +210,7 @@
     public AnAction[] getChildren(@Nullable AnActionEvent e) {
       List<AnAction> branchHeadActions = new ArrayList<AnAction>();
       for (Hash hash : myHeads) {
-        branchHeadActions.add(new BranchActions(myProject, hash.toShortString(), myRepository));
+        branchHeadActions.add(new HgCommonBranchActions(myProject, myRepository, hash.toShortString()));
       }
       return ContainerUtil.toArray(branchHeadActions, new AnAction[branchHeadActions.size()]);
     }
@@ -246,117 +227,35 @@
     }
   }
 
-
   /**
-   * Actions available for  branches.
+   * Actions available for  bookmarks.
    */
-  static class BranchActions extends ActionGroup {
+  static class BookmarkActions extends HgCommonBranchActions {
 
-    private final Project myProject;
-    private String myBranchName;
-    @NotNull private final HgRepository mySelectedRepository;
-
-    BranchActions(@NotNull Project project, @NotNull String branchName,
-                  @NotNull HgRepository selectedRepository) {
-      super("", true);
-      myProject = project;
-      myBranchName = branchName;
-      mySelectedRepository = selectedRepository;
-      getTemplatePresentation().setText(calcBranchText(), false); // no mnemonics
-    }
-
-    @NotNull
-    private String calcBranchText() {
-      return myBranchName;
+    BookmarkActions(@NotNull Project project, @NotNull HgRepository selectedRepository, @NotNull String branchName) {
+      super(project, selectedRepository, branchName);
     }
 
     @NotNull
     @Override
     public AnAction[] getChildren(@Nullable AnActionEvent e) {
-      return new AnAction[]{
-        new UpdateToAction(myProject, mySelectedRepository, myBranchName),
-        new MergeAction(myProject, mySelectedRepository, myBranchName)
-      };
+      return ArrayUtil.append(super.getChildren(e), new DeleteBookmarkAction(myProject, mySelectedRepository, myBranchName));
     }
 
-    private static class MergeAction extends DumbAwareAction {
+    private static class DeleteBookmarkAction extends HgBranchAbstractAction {
 
-      private final Project myProject;
-      private final HgRepository mySelectedRepository;
-      private final String myBranchName;
-
-      public MergeAction(@NotNull Project project,
-                         @NotNull HgRepository selectedRepository,
-                         @NotNull String branchName) {
-        super("Merge");
-        myProject = project;
-        mySelectedRepository = selectedRepository;
-        myBranchName = branchName;
+      DeleteBookmarkAction(@NotNull Project project, @NotNull HgRepository selectedRepository, @NotNull String branchName) {
+        super(project, "Delete", selectedRepository, branchName);
       }
 
       @Override
       public void actionPerformed(AnActionEvent e) {
-        final UpdatedFiles updatedFiles = UpdatedFiles.create();
-        final HgMergeCommand hgMergeCommand = new HgMergeCommand(myProject, mySelectedRepository.getRoot());
-        hgMergeCommand.setBranch(myBranchName);
-        final HgCommandResultNotifier notifier = new HgCommandResultNotifier(myProject);
-        new Task.Backgroundable(myProject, "Merging changes...") {
-          @Override
-          public void run(@NotNull ProgressIndicator indicator) {
-            try {
-              new HgHeadMerger(myProject, hgMergeCommand)
-                .merge(mySelectedRepository.getRoot(), updatedFiles, HgRevisionNumber.NULL_REVISION_NUMBER);
-              new HgConflictResolver(myProject, updatedFiles).resolve(mySelectedRepository.getRoot());
-            }
-
-            catch (VcsException exception) {
-              if (exception.isWarning()) {
-                notifier.notifyWarning("Warning during merge", exception.getMessage());
-              }
-              else {
-                notifier.notifyError(null, "Exception during merge", exception.getMessage());
-              }
-            }
-            catch (Exception e1) {
-              HgAbstractGlobalAction.handleException(myProject, e1);
-            }
-          }
-        }.queue();
-      }
-    }
-
-    private static class UpdateToAction extends DumbAwareAction {
-
-      @NotNull private final Project myProject;
-      @NotNull private final HgRepository mySelectedRepository;
-      @NotNull private final String myBranch;
-
-      public UpdateToAction(@NotNull Project project,
-                            @NotNull HgRepository selectedRepository,
-                            @NotNull String branch) {
-        super("Update To");
-        myProject = project;
-        mySelectedRepository = selectedRepository;
-        myBranch = branch;
-      }
-
-      @Override
-      public void actionPerformed(AnActionEvent e) {
-        final VirtualFile repository = mySelectedRepository.getRoot();
-        final HgUpdateCommand hgUpdateCommand = new HgUpdateCommand(myProject, repository);
-        hgUpdateCommand.setBranch(myBranch);
-        new Task.Backgroundable(myProject, HgVcsMessages.message("action.hg4idea.updateTo.description", myBranch)) {
-          @Override
-          public void run(@NotNull ProgressIndicator indicator) {
-            HgCommandResult result = hgUpdateCommand.execute();
-            assert myProject != null;  // myProject couldn't be null, see annotation for updateTo action
-            if (HgErrorUtil.hasErrorsInCommandExecution(result)) {
-              new HgCommandResultNotifier(myProject).notifyError(result, "", "Update failed");
-              new HgConflictResolver(myProject).resolve(repository);
-            }
-            myProject.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(myProject, null);
-          }
-        }.queue();
+        try {
+          new HgBookmarkCommand(myProject, mySelectedRepository.getRoot(), myBranchName).deleteBookmark();
+        }
+        catch (HgCommandException exception) {
+          HgAbstractGlobalAction.handleException(myProject, exception);
+        }
       }
     }
   }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java
index 61cf991..b8a10ed 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java
@@ -16,34 +16,18 @@
 package org.zmlx.hg4idea.action;
 
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.repo.HgRepository;
-import org.zmlx.hg4idea.util.HgUtil;
 
 import java.util.Collection;
 
-/**
- * @author Nadya Zabrodina
- */
-
 public class HgBranchesAction extends HgAbstractGlobalAction {
 
   @Override
-  protected void execute(@NotNull Project project, @NotNull Collection<VirtualFile> repositories, @Nullable VirtualFile selectedRepo) {
-    HgRepository repository = null;
+  protected void execute(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
     if (selectedRepo != null) {
-      repository = HgUtil.getRepositoryManager(project).getRepositoryForRoot(selectedRepo);
-    }
-    else {
-      VirtualFile selectedRoot = HgUtil.getRootForSelectedFile(project);
-      if (selectedRoot != null) {
-        repository = HgUtil.getRepositoryManager(project).getRepositoryForRoot(selectedRoot);
-      }
-    }
-    if (repository != null) {
-      HgBranchPopup.getInstance(project, repository).asListPopup().showInFocusCenter();
+      HgBranchPopup.getInstance(project, selectedRepo).asListPopup().showInFocusCenter();
     }
   }
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java
new file mode 100644
index 0000000..992a26c
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ * 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 org.zmlx.hg4idea.action;
+
+import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.update.UpdatedFiles;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.HgVcs;
+import org.zmlx.hg4idea.HgVcsMessages;
+import org.zmlx.hg4idea.command.HgMergeCommand;
+import org.zmlx.hg4idea.command.HgUpdateCommand;
+import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.provider.update.HgConflictResolver;
+import org.zmlx.hg4idea.provider.update.HgHeadMerger;
+import org.zmlx.hg4idea.repo.HgRepository;
+import org.zmlx.hg4idea.util.HgErrorUtil;
+
+public class HgCommonBranchActions extends ActionGroup {
+
+  @NotNull protected final Project myProject;
+  @NotNull protected String myBranchName;
+  @NotNull protected final HgRepository mySelectedRepository;
+
+  HgCommonBranchActions(@NotNull Project project, @NotNull HgRepository selectedRepository, @NotNull String branchName) {
+    super("", true);
+    myProject = project;
+    myBranchName = branchName;
+    mySelectedRepository = selectedRepository;
+    getTemplatePresentation().setText(myBranchName, false); // no mnemonics
+  }
+
+  @NotNull
+  @Override
+  public AnAction[] getChildren(@Nullable AnActionEvent e) {
+    return new AnAction[]{
+      new UpdateAction(myProject, mySelectedRepository, myBranchName),
+      new MergeAction(myProject, mySelectedRepository, myBranchName)
+    };
+  }
+
+  private static class MergeAction extends HgBranchAbstractAction {
+
+    public MergeAction(@NotNull Project project,
+                       @NotNull HgRepository selectedRepository,
+                       @NotNull String branchName) {
+      super(project, "Merge", selectedRepository, branchName);
+    }
+
+    @Override
+    public void actionPerformed(AnActionEvent e) {
+      final UpdatedFiles updatedFiles = UpdatedFiles.create();
+      final HgMergeCommand hgMergeCommand = new HgMergeCommand(myProject, mySelectedRepository.getRoot());
+      hgMergeCommand.setRevision(myBranchName);//there is no difference between branch or revision or bookmark as parameter to merge,
+      // we need just a string
+      final HgCommandResultNotifier notifier = new HgCommandResultNotifier(myProject);
+      new Task.Backgroundable(myProject, "Merging changes...") {
+        @Override
+        public void run(@NotNull ProgressIndicator indicator) {
+          try {
+            new HgHeadMerger(myProject, hgMergeCommand)
+              .merge(mySelectedRepository.getRoot());
+            new HgConflictResolver(myProject, updatedFiles).resolve(mySelectedRepository.getRoot());
+          }
+
+          catch (VcsException exception) {
+            if (exception.isWarning()) {
+              notifier.notifyWarning("Warning during merge", exception.getMessage());
+            }
+            else {
+              notifier.notifyError(null, "Exception during merge", exception.getMessage());
+            }
+          }
+          catch (Exception e1) {
+            HgAbstractGlobalAction.handleException(myProject, e1);
+          }
+        }
+      }.queue();
+    }
+  }
+
+  private static class UpdateAction extends HgBranchAbstractAction {
+
+    public UpdateAction(@NotNull Project project,
+                        @NotNull HgRepository selectedRepository,
+                        @NotNull String branchName) {
+      super(project, "Update", selectedRepository, branchName);
+    }
+
+    @Override
+    public void actionPerformed(AnActionEvent e) {
+      final VirtualFile repository = mySelectedRepository.getRoot();
+      final HgUpdateCommand hgUpdateCommand = new HgUpdateCommand(myProject, repository);
+      hgUpdateCommand.setBranch(myBranchName);
+      new Task.Backgroundable(myProject, HgVcsMessages.message("action.hg4idea.updateTo.description", myBranchName)) {
+        @Override
+        public void run(@NotNull ProgressIndicator indicator) {
+          HgCommandResult result = hgUpdateCommand.execute();
+          assert myProject != null;  // myProject couldn't be null, see annotation for updateTo action
+          if (HgErrorUtil.hasErrorsInCommandExecution(result)) {
+            new HgCommandResultNotifier(myProject).notifyError(result, "", "Update failed");
+            new HgConflictResolver(myProject).resolve(repository);
+          }
+          myProject.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(myProject, null);
+        }
+      }.queue();
+    }
+  }
+}
\ No newline at end of file
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
index 1aec1a0..5c97e3c 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
@@ -13,13 +13,13 @@
 package org.zmlx.hg4idea.action;
 
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.command.HgTagCreateCommand;
 import org.zmlx.hg4idea.execution.HgCommandException;
 import org.zmlx.hg4idea.execution.HgCommandResult;
 import org.zmlx.hg4idea.execution.HgCommandResultHandler;
+import org.zmlx.hg4idea.repo.HgRepository;
 import org.zmlx.hg4idea.ui.HgTagDialog;
 import org.zmlx.hg4idea.util.HgErrorUtil;
 
@@ -28,11 +28,10 @@
 public class HgCreateTagAction extends HgAbstractGlobalAction {
 
   public void execute(@NotNull final Project project,
-                      @NotNull Collection<VirtualFile> repos,
-                      @Nullable VirtualFile selectedRepo,
+                      @NotNull Collection<HgRepository> repositories,
+                      @Nullable HgRepository selectedRepo,
                       @Nullable final String reference) {
-    final HgTagDialog dialog = new HgTagDialog(project);
-    dialog.setRoots(repos, selectedRepo);
+    final HgTagDialog dialog = new HgTagDialog(project, repositories, selectedRepo);
     dialog.show();
     if (dialog.isOK()) {
       try {
@@ -52,7 +51,9 @@
     }
   }
 
-  protected void execute(@NotNull final Project project, @NotNull Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
-    execute(project, repos, selectedRepo, null);
+  protected void execute(@NotNull final Project project,
+                         @NotNull Collection<HgRepository> repositories,
+                         @Nullable HgRepository selectedRepo) {
+    execute(project, repositories, selectedRepo, null);
   }
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java
index 18a42d7..03f6f95 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java
@@ -19,15 +19,12 @@
 import org.jetbrains.annotations.NotNull;
 import org.zmlx.hg4idea.repo.HgRepository;
 
-import java.util.Arrays;
+import java.util.Collections;
 
-/**
- * @author Nadya Zabrodina
- */
 public class HgCreateTagFromLogAction extends HgLogSingleCommitAction {
   @Override
   protected void actionPerformed(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit) {
     String revisionHash = commit.getHash().asString();
-    new HgCreateTagAction().execute(repository.getProject(), Arrays.asList(repository.getRoot()), repository.getRoot(), revisionHash);
+    new HgCreateTagAction().execute(repository.getProject(), Collections.singleton(repository), repository, revisionHash);
   }
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java
index fe022bc..87c907d 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java
@@ -18,56 +18,37 @@
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vcs.VcsException;
 import com.intellij.openapi.vcs.update.UpdatedFiles;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Consumer;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.HgRevisionNumber;
-import org.zmlx.hg4idea.HgVcsMessages;
 import org.zmlx.hg4idea.command.HgMergeCommand;
-import org.zmlx.hg4idea.command.HgTagBranch;
 import org.zmlx.hg4idea.execution.HgCommandException;
 import org.zmlx.hg4idea.provider.update.HgConflictResolver;
 import org.zmlx.hg4idea.provider.update.HgHeadMerger;
+import org.zmlx.hg4idea.repo.HgRepository;
 import org.zmlx.hg4idea.ui.HgMergeDialog;
-import org.zmlx.hg4idea.util.HgBranchesAndTags;
-import org.zmlx.hg4idea.util.HgUiUtil;
 
 import java.util.Collection;
 
-/**
- * @author Nadya Zabrodina
- */
 public class HgMerge extends HgAbstractGlobalAction {
 
   @Override
   public void execute(@NotNull final Project project,
-                      @NotNull final Collection<VirtualFile> repos,
-                      @Nullable final VirtualFile selectedRepo) {
-    HgUiUtil.loadBranchesInBackgroundableAndExecuteAction(project, repos, new Consumer<HgBranchesAndTags>() {
-
-      @Override
-      public void consume(HgBranchesAndTags info) {
-        showMergeDialogAndExecute(project, repos, selectedRepo, info);
-      }
-    });
-  }
-
-  private void showMergeDialogAndExecute(final Project project,
-                                         Collection<VirtualFile> repos,
-                                         @Nullable VirtualFile selectedRepo, HgBranchesAndTags branchesAndTags) {
-    final HgMergeDialog mergeDialog = new HgMergeDialog(project, repos, selectedRepo, branchesAndTags);
+                      @NotNull final Collection<HgRepository> repos,
+                      @Nullable final HgRepository selectedRepo) {
+    final HgMergeDialog mergeDialog = new HgMergeDialog(project, repos, selectedRepo);
     mergeDialog.show();
     if (mergeDialog.isOK()) {
+      final String targetValue = mergeDialog.getTargetValue();
+      final VirtualFile repoRoot = mergeDialog.getRepository().getRoot();
       new Task.Backgroundable(project, "Merging changes...") {
         @Override
         public void run(@NotNull ProgressIndicator indicator) {
           try {
-            executeMerge(mergeDialog, project);
-            markDirtyAndHandleErrors(project, mergeDialog.getRepository());
+            executeMerge(project, repoRoot, targetValue);
+            markDirtyAndHandleErrors(project, repoRoot);
           }
           catch (HgCommandException e) {
             handleException(project, e);
@@ -77,63 +58,26 @@
     }
   }
 
-  private static void executeMerge(final HgMergeDialog dialog, final Project project) throws HgCommandException {
+
+  private static void executeMerge(@NotNull final Project project, @NotNull VirtualFile repo, @NotNull String targetValue)
+    throws HgCommandException {
     UpdatedFiles updatedFiles = UpdatedFiles.create();
     HgCommandResultNotifier notifier = new HgCommandResultNotifier(project);
-    final VirtualFile repo = dialog.getRepository();
 
     HgMergeCommand hgMergeCommand = new HgMergeCommand(project, repo);
+    hgMergeCommand.setRevision(targetValue);
 
-    HgRevisionNumber incomingRevision = null;
-    HgTagBranch branch = dialog.getBranch();
-    if (branch != null) {
-      hgMergeCommand.setBranch(branch.getName());
-      incomingRevision = branch.getHead();
+    try {
+      new HgHeadMerger(project, hgMergeCommand).merge(repo);
+      new HgConflictResolver(project, updatedFiles).resolve(repo);
     }
-
-    HgTagBranch tag = dialog.getTag();
-    if (tag != null) {
-      hgMergeCommand.setRevision(tag.getName());
-      incomingRevision = tag.getHead();
-    }
-
-    HgTagBranch bookmark = dialog.getBookmark();
-    if (bookmark != null) {
-      hgMergeCommand.setRevision(bookmark.getName());
-      incomingRevision = bookmark.getHead();
-    }
-
-    String revision = dialog.getRevision();
-    if (revision != null) {
-      hgMergeCommand.setRevision(revision);
-      incomingRevision = HgRevisionNumber.getLocalInstance(revision);
-    }
-
-    HgRevisionNumber otherHead = dialog.getOtherHead();
-    if (otherHead != null) {
-      String changeset = otherHead.getChangeset();
-      hgMergeCommand.setRevision(StringUtil.isEmptyOrSpaces(changeset) ? otherHead.getRevision() : changeset);
-      incomingRevision = otherHead;
-    }
-
-    if (incomingRevision != null) {
-      try {
-        new HgHeadMerger(project, hgMergeCommand)
-          .merge(repo, updatedFiles, incomingRevision);
-        new HgConflictResolver(project, updatedFiles).resolve(repo);
+    catch (VcsException e) {
+      if (e.isWarning()) {
+        notifier.notifyWarning("Warning during merge", e.getMessage());
       }
-      catch (VcsException e) {
-        if (e.isWarning()) {
-          notifier.notifyWarning("Warning during merge", e.getMessage());
-        }
-        else {
-          notifier.notifyError(null, "Exception during merge", e.getMessage());
-        }
+      else {
+        notifier.notifyError(null, "Exception during merge", e.getMessage());
       }
     }
-    else {
-      //noinspection ThrowableInstanceNeverThrown
-      notifier.notifyError(null, "Merge error", HgVcsMessages.message("hg4idea.error.invalidTarget"));
-    }
   }
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java
index 136a50e..557d3cf 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java
@@ -16,10 +16,10 @@
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.command.HgPullCommand;
+import org.zmlx.hg4idea.repo.HgRepository;
 import org.zmlx.hg4idea.ui.HgPullDialog;
 
 import java.util.Collection;
@@ -30,9 +30,8 @@
   }
 
   @Override
-  protected void execute(@NotNull final Project project, @NotNull Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
-    final HgPullDialog dialog = new HgPullDialog(project);
-    dialog.setRoots(repos, selectedRepo);
+  protected void execute(@NotNull final Project project, @NotNull Collection<HgRepository> repos, @Nullable HgRepository selectedRepo) {
+    final HgPullDialog dialog = new HgPullDialog(project, repos, selectedRepo);
     dialog.show();
     if (dialog.isOK()) {
       dialog.rememberSettings();
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
index ae6206c..1b5704f 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
@@ -14,18 +14,22 @@
 
 import com.intellij.icons.AllIcons;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgPusher;
+import org.zmlx.hg4idea.repo.HgRepository;
 
-public class HgPushAction extends HgAction {
+import java.util.Collection;
+
+public class HgPushAction extends HgAbstractGlobalAction {
   public HgPushAction() {
     super(AllIcons.Actions.Commit);
   }
 
   @Override
-  public void execute(final Project project, @Nullable final VirtualFile selectedRepo) {
-    new HgPusher(project).showDialogAndPush(selectedRepo);
+  public void execute(@NotNull final Project project,
+                      @NotNull Collection<HgRepository> repositories,
+                      @Nullable final HgRepository selectedRepo) {
+    new HgPusher(project).showDialogAndPush(repositories, selectedRepo);
   }
-
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java
index 3be82ad..938413e 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java
@@ -15,11 +15,12 @@
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgVcsMessages;
 import org.zmlx.hg4idea.provider.update.HgConflictResolver;
+import org.zmlx.hg4idea.repo.HgRepository;
 import org.zmlx.hg4idea.ui.HgRunConflictResolverDialog;
 
 import java.util.Collection;
@@ -27,39 +28,26 @@
 public class HgRunConflictResolverAction extends HgAbstractGlobalAction {
 
   @Override
-  public void execute(@NotNull final Project project, @NotNull Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
-    final VirtualFile repository;
-    if (repos.size() > 1) {
-      repository = letUserSelectRepository(repos, project, selectedRepo);
-    }
-    else if (repos.size() == 1) {
-      repository = repos.iterator().next();
-    }
-    else {
-      repository = null;
-    }
+  public void execute(@NotNull final Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
+    final HgRepository repository = repositories.size() > 1 ? letUserSelectRepository(project, repositories, selectedRepo) :
+                                    ContainerUtil.getFirstItem(repositories);
     if (repository != null) {
       new Task.Backgroundable(project, HgVcsMessages.message("action.hg4idea.run.conflict.resolver.description")) {
 
         @Override
         public void run(@NotNull ProgressIndicator indicator) {
-          new HgConflictResolver(project).resolve(repository);
-          markDirtyAndHandleErrors(project, repository);
+          new HgConflictResolver(project).resolve(repository.getRoot());
+          markDirtyAndHandleErrors(project, repository.getRoot());
         }
       }.queue();
     }
   }
 
-
-  private static VirtualFile letUserSelectRepository(Collection<VirtualFile> repos, Project project, @Nullable VirtualFile selectedRepo) {
-    HgRunConflictResolverDialog dialog = new HgRunConflictResolverDialog(project);
-    dialog.setRoots(repos, selectedRepo);
+  @Nullable
+  private static HgRepository letUserSelectRepository(@NotNull Project project, @NotNull Collection<HgRepository> repositories,
+                                                      @Nullable HgRepository selectedRepo) {
+    HgRunConflictResolverDialog dialog = new HgRunConflictResolverDialog(project, repositories, selectedRepo);
     dialog.show();
-    if (dialog.isOK()) {
-      return dialog.getRepository();
-    }
-    else {
-      return null;
-    }
+    return dialog.isOK() ? dialog.getRepository() : null;
   }
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
index 1a2cdea..7e10259 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
@@ -17,61 +17,43 @@
 import com.intellij.openapi.progress.Task;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Consumer;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgVcsMessages;
 import org.zmlx.hg4idea.command.HgUpdateCommand;
 import org.zmlx.hg4idea.execution.HgCommandResult;
 import org.zmlx.hg4idea.provider.update.HgConflictResolver;
+import org.zmlx.hg4idea.repo.HgRepository;
 import org.zmlx.hg4idea.ui.HgUpdateToDialog;
-import org.zmlx.hg4idea.util.HgBranchesAndTags;
 import org.zmlx.hg4idea.util.HgErrorUtil;
-import org.zmlx.hg4idea.util.HgUiUtil;
 
 import java.util.Collection;
 
 public class HgUpdateToAction extends HgAbstractGlobalAction {
 
-  protected void execute(@NotNull final Project project,
-                         @NotNull final Collection<VirtualFile> repos,
-                         @Nullable final VirtualFile selectedRepo) {
-    HgUiUtil.loadBranchesInBackgroundableAndExecuteAction(project, repos, new Consumer<HgBranchesAndTags>() {
-      @Override
-      public void consume(HgBranchesAndTags info) {
-        showUpdateDialogAndExecute(project, repos, selectedRepo, info);
-      }
-    });
-  }
-
-  private static void showUpdateDialogAndExecute(@NotNull final Project project,
-                                                 @NotNull Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo,
-                                                 @NotNull HgBranchesAndTags branchesAndTags) {
-    final HgUpdateToDialog dialog = new HgUpdateToDialog(project);
-    dialog.setRoots(repos, selectedRepo, branchesAndTags);
+  @Override
+  protected void execute(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
+    final HgUpdateToDialog dialog = new HgUpdateToDialog(project, repositories, selectedRepo);
     dialog.show();
     if (dialog.isOK()) {
       FileDocumentManager.getInstance().saveAllDocuments();
-      final String updateToValue = dialog.isBranchSelected()
-                                   ? dialog.getBranch().getName()
-                                   : dialog.isBookmarkSelected()
-                                     ? dialog.getBookmark().getName()
-                                     : dialog.isTagSelected() ? dialog.getTag().getName() : dialog.getRevision();
+      final String updateToValue = dialog.getTargetValue();
+      boolean clean = dialog.isRemoveLocalChanges();
       String title = HgVcsMessages.message("hg4idea.progress.updatingTo", updateToValue);
-      runUpdateToInBackground(project, title, dialog.getRepository(), updateToValue, dialog.isRemoveLocalChanges());
+      runUpdateToInBackground(project, title, dialog.getRepository().getRoot(), updateToValue, clean);
     }
   }
 
   public static void runUpdateToInBackground(@NotNull final Project project,
                                              @NotNull String title,
                                              @NotNull final VirtualFile root,
-                                             @NotNull final String updateToNameOrRevision,
+                                             @NotNull final String updateToValue,
                                              final boolean clean) {
     new Task.Backgroundable(project, title) {
       @Override
       public void run(@NotNull ProgressIndicator indicator) {
         final HgUpdateCommand command = new HgUpdateCommand(project, root);
-        command.setRevision(updateToNameOrRevision);
+        command.setRevision(updateToValue);
         command.setClean(clean);
         HgCommandResult result = command.execute();
         new HgConflictResolver(project).resolve(root);
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgBookmarkCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgBookmarkCommand.java
new file mode 100644
index 0000000..21b4edd
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgBookmarkCommand.java
@@ -0,0 +1,65 @@
+package org.zmlx.hg4idea.command;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.action.HgCommandResultNotifier;
+import org.zmlx.hg4idea.execution.HgCommandException;
+import org.zmlx.hg4idea.execution.HgCommandExecutor;
+import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.execution.HgCommandResultHandler;
+import org.zmlx.hg4idea.util.HgErrorUtil;
+
+import java.util.List;
+
+import static org.zmlx.hg4idea.util.HgUtil.getRepositoryManager;
+
+public class HgBookmarkCommand {
+  @NotNull private final Project myProject;
+  @NotNull private final VirtualFile myRepo;
+  @Nullable private final String myBookmarkName;
+  @NotNull private final HgCommandResultHandler myBookmarkResultHandler;
+
+  public HgBookmarkCommand(@NotNull Project project,
+                           @NotNull VirtualFile repo,
+                           @Nullable String bookmarkName) {
+    myProject = project;
+    myRepo = repo;
+    myBookmarkName = bookmarkName;
+    myBookmarkResultHandler = new HgCommandResultHandler() {
+      @Override
+      public void process(@Nullable HgCommandResult result) {
+        getRepositoryManager(myProject).updateRepository(myRepo);
+        if (HgErrorUtil.hasErrorsInCommandExecution(result)) {
+          new HgCommandResultNotifier(myProject)
+            .notifyError(result, "Hg Error", "Hg bookmark command failed for " + myBookmarkName);
+        }
+      }
+    };
+  }
+
+  public void createBookmark(boolean isActive) throws HgCommandException {
+    if (isActive) {
+      executeBookmarkCommand();
+    }
+    else {
+      executeBookmarkCommand("--inactive");
+    }
+  }
+
+  public void deleteBookmark() throws HgCommandException {
+    executeBookmarkCommand("-d");  //delete
+  }
+
+  private void executeBookmarkCommand(@NotNull String... args) throws HgCommandException {
+    if (StringUtil.isEmptyOrSpaces(myBookmarkName)) {
+      throw new HgCommandException("bookmark name is empty");
+    }
+    List<String> arguments = ContainerUtil.newArrayList(args);
+    arguments.add(myBookmarkName);
+    new HgCommandExecutor(myProject).execute(myRepo, "bookmark", arguments, myBookmarkResultHandler);
+  }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgBookmarkCreateCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgBookmarkCreateCommand.java
deleted file mode 100644
index 89442ef..0000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgBookmarkCreateCommand.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.zmlx.hg4idea.command;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.execution.HgCommandException;
-import org.zmlx.hg4idea.execution.HgCommandExecutor;
-import org.zmlx.hg4idea.execution.HgCommandResultHandler;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Nadya Zabrodina
- */
-public class HgBookmarkCreateCommand {
-  @NotNull private final Project myProject;
-  @NotNull private final VirtualFile myRepo;
-  @Nullable private final String myBookmarkName;
-  private final boolean isActive;
-
-  public HgBookmarkCreateCommand(@NotNull Project project,
-                                 @NotNull VirtualFile repo,
-                                 @Nullable String bookmarkName,
-                                 boolean active) {
-    myProject = project;
-    myRepo = repo;
-    myBookmarkName = bookmarkName;
-    isActive = active;
-  }
-
-  public void execute(@Nullable HgCommandResultHandler resultHandler) throws HgCommandException {
-    if (StringUtil.isEmptyOrSpaces(myBookmarkName)) {
-      throw new HgCommandException("bookmark name is empty");
-    }
-    List<String> arguments = new ArrayList<String>();
-    arguments.add(myBookmarkName);
-    if (!isActive) {
-      arguments.add("--inactive");
-    }
-    new HgCommandExecutor(myProject).execute(myRepo, "bookmark", arguments, resultHandler);
-  }
-}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgBranchesCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgBranchesCommand.java
new file mode 100644
index 0000000..430e7e1
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgBranchesCommand.java
@@ -0,0 +1,56 @@
+// Copyright 2008-2010 Victor Iacoban
+//
+// 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 org.zmlx.hg4idea.command;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.execution.HgCommandExecutor;
+import org.zmlx.hg4idea.execution.HgCommandResult;
+
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class HgBranchesCommand {
+
+  private static final Pattern BRANCH_LINE = Pattern.compile("(.+)\\s([0-9]+):([0-9a-f]+).*");
+  private static final int NAME_INDEX = 1;
+
+  private final Project project;
+  private final VirtualFile repo;
+
+  public HgBranchesCommand(Project project, @NotNull VirtualFile repo) {
+    this.project = project;
+    this.repo = repo;
+  }
+
+  @Nullable
+  public HgCommandResult collectBranches() {
+    return new HgCommandExecutor(project).executeInCurrentThread(repo, "branches", null);
+  }
+
+  @NotNull
+  public static Set<String> collectNames(@NotNull HgCommandResult result) {
+    Set<String> branches = new HashSet<String>();
+    for (final String line : result.getOutputLines()) {
+      Matcher matcher = BRANCH_LINE.matcher(line);
+      if (matcher.matches()) {
+        branches.add(matcher.group(NAME_INDEX).trim());
+      }
+    }
+    return branches;
+  }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgMergeCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgMergeCommand.java
index d8d70f0..ad10a37 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgMergeCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgMergeCommand.java
@@ -15,6 +15,7 @@
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgVcs;
 import org.zmlx.hg4idea.execution.HgCommandExecutor;
@@ -26,22 +27,17 @@
 
 public class HgMergeCommand {
 
-  private final Project project;
-  private final VirtualFile repo;
+  @NotNull private final Project project;
+  @NotNull private final VirtualFile repo;
 
-  private String branch;
   private String revision;
 
-  public HgMergeCommand(Project project, VirtualFile repo) {
+  public HgMergeCommand(@NotNull Project project, @NotNull VirtualFile repo) {
     this.project = project;
     this.repo = repo;
   }
 
-  public void setBranch(String branch) {
-    this.branch = branch;
-  }
-
-  public void setRevision(String revision) {
+  public void setRevision(@NotNull String revision) {
     this.revision = revision;
   }
 
@@ -53,13 +49,10 @@
     if (!StringUtil.isEmptyOrSpaces(revision)) {
       arguments.add("--rev");
       arguments.add(revision);
-    } else if (!StringUtil.isEmptyOrSpaces(branch)) {
-      arguments.add(branch);
     }
     final HgCommandResult result =
       commandExecutor.executeInCurrentThread(repo, "merge", arguments, new HgDeleteModifyPromptHandler());
     project.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(project, null);
     return result;
   }
-
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPushCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPushCommand.java
index 357fa89..1674846 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPushCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPushCommand.java
@@ -33,7 +33,8 @@
 
   private String myRevision;
   private boolean myForce;
-  private HgTagBranch myBranch;
+  private String myBranchName;
+  private String myBookmarkName;
   private boolean myIsNewBranch;
 
   public HgPushCommand(Project project, @NotNull VirtualFile repo, String destination) {
@@ -50,13 +51,17 @@
     myForce = force;
   }
 
-  public void setBranch(HgTagBranch branch) {
-    myBranch = branch;
+  public void setBranchName(String branchName) {
+    myBranchName = branchName;
   }
 
   public void setIsNewBranch(boolean isNewBranch) {
-      myIsNewBranch = isNewBranch;
-    }
+    myIsNewBranch = isNewBranch;
+  }
+
+  public void setBookmarkName(String bookmark) {
+    myBookmarkName = bookmark;
+  }
 
   public void execute(final HgCommandResultHandler resultHandler) {
     final List<String> arguments = new LinkedList<String>();
@@ -64,15 +69,19 @@
       arguments.add("-r");
       arguments.add(myRevision);
     }
-    if (myBranch != null) {
+    if (myBranchName != null) {
       if (myIsNewBranch) {
         arguments.add("--new-branch");
       }
       else {
         arguments.add("-b");
-        arguments.add(myBranch.getName());
+        arguments.add(myBranchName);
       }
     }
+    if (!StringUtil.isEmptyOrSpaces(myBookmarkName)) {
+      arguments.add("-B");
+      arguments.add(myBookmarkName);
+    }
     if (myForce) {
       arguments.add("-f");
     }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagBranch.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagBranch.java
deleted file mode 100644
index cf4325a..0000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagBranch.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2008-2010 Victor Iacoban
-//
-// 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 org.zmlx.hg4idea.command;
-
-import com.intellij.openapi.util.text.StringUtil;
-import org.zmlx.hg4idea.HgRevisionNumber;
-
-public final class HgTagBranch {
-
-  private static final int SPACINGAFTERFIRSTLETTER = 20;
-
-  private final String name;
-  private final String description;
-  private final HgRevisionNumber head;
-  private final String presentation;
-
-  public HgTagBranch(String name, String description, HgRevisionNumber head) {
-    this.name = name;
-    this.description = description;
-    this.head = head;
-    int whitespaceNum = SPACINGAFTERFIRSTLETTER - name.length();
-    String presentationName = whitespaceNum <= 0 ? name.substring(0, SPACINGAFTERFIRSTLETTER - 4).concat("...") : name;
-    presentation = String.format("%s%s%s", presentationName, whitespaceNum > 0 ? StringUtil.repeatSymbol(' ', whitespaceNum) : " ", head);
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public String getDescription() {
-    return description;
-  }
-
-  public HgRevisionNumber getHead() {
-    return head;
-  }
-
-  @Override
-  public String toString() {
-    return presentation;
-  }
-}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagBranchCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagBranchCommand.java
deleted file mode 100644
index 7c1aa06..0000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagBranchCommand.java
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2008-2010 Victor Iacoban
-//
-// 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 org.zmlx.hg4idea.command;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.containers.HashSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.HgRevisionNumber;
-import org.zmlx.hg4idea.execution.HgCommandExecutor;
-import org.zmlx.hg4idea.execution.HgCommandResult;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class HgTagBranchCommand {
-
-  private static final Pattern BRANCH_LINE = Pattern.compile("(.+)\\s([0-9]+):([0-9a-f]+).*");
-  private static final int NAME_INDEX = 1;
-  private static final int REVISION_INDEX = 2;
-  private static final int CHANGESET_INDEX = 3;
-
-  private final Project project;
-  private final VirtualFile repo;
-
-  public HgTagBranchCommand(Project project, @NotNull VirtualFile repo) {
-    this.project = project;
-    this.repo = repo;
-  }
-
-  @Nullable
-  public String getCurrentBranch() {
-    final HgCommandExecutor executor = new HgCommandExecutor(project);
-    executor.setSilent(true);
-    HgCommandResult result = executor.executeInCurrentThread(repo, "branch", null);
-    if (result == null) {
-      return null;
-    }
-    List<String> output = result.getOutputLines();
-    if (output == null || output.isEmpty()) {
-      return null;
-    }
-    return output.get(0).trim();
-  }
-
-  public HgCommandResult collectBranches() {
-    return new HgCommandExecutor(project).executeInCurrentThread(repo, "branches", null);
-  }
-
-  public HgCommandResult collectTags() {
-    return new HgCommandExecutor(project).executeInCurrentThread(repo, "tags", null);
-  }
-
-  public HgCommandResult collectBookmarks() {
-    return new HgCommandExecutor(project).executeInCurrentThread(repo, "bookmarks", null);
-  }
-
-  public static List<HgTagBranch> parseResult(@NotNull HgCommandResult result) {
-    List<HgTagBranch> branches = new LinkedList<HgTagBranch>();
-    for (final String line : result.getOutputLines()) {
-      Matcher matcher = BRANCH_LINE.matcher(line);
-      if (matcher.matches()) {
-        HgRevisionNumber hgRevisionNumber = HgRevisionNumber.getInstance(
-          matcher.group(REVISION_INDEX), matcher.group(CHANGESET_INDEX)
-        );
-        branches.add(new HgTagBranch(matcher.group(NAME_INDEX).trim(), line.trim(), hgRevisionNumber));
-      }
-    }
-    return branches;
-  }
-
-  @NotNull
-  public static Set<String> collectNames(@NotNull HgCommandResult result) {
-    Set<String> branches = new HashSet<String>();
-    for (final String line : result.getOutputLines()) {
-      Matcher matcher = BRANCH_LINE.matcher(line);
-      if (matcher.matches()) {
-        branches.add(matcher.group(NAME_INDEX).trim());
-      }
-    }
-    return branches;
-  }
-}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java
index aaf9e9d..dec0e72 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java
@@ -40,6 +40,8 @@
 import org.zmlx.hg4idea.execution.HgCommandException;
 import org.zmlx.hg4idea.execution.HgCommandExecutor;
 import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.repo.HgRepository;
+import org.zmlx.hg4idea.repo.HgRepositoryManager;
 import org.zmlx.hg4idea.util.HgUtil;
 
 import java.util.*;
@@ -125,9 +127,12 @@
     // push if needed
     if (myNextCommitIsPushed && exceptions.isEmpty()) {
       final VirtualFile preselectedRepo = repositoriesMap.size() == 1 ? repositoriesMap.keySet().iterator().next() : null;
+      HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(myProject);
+      final HgRepository repo = preselectedRepo != null ? repositoryManager.getRepositoryForFile(preselectedRepo) : null;
+      final Collection<HgRepository> repositories = repositoryManager.getRepositories();
       UIUtil.invokeLaterIfNeeded(new Runnable() {
         public void run() {
-          new HgPusher(myProject).showDialogAndPush(preselectedRepo);
+          new HgPusher(myProject).showDialogAndPush(repositories, repo);
         }
       });
     }
@@ -264,31 +269,33 @@
     public HgCommitAdditionalComponent(@NotNull Project project, @NotNull CheckinProjectPanel panel) {
       super(project, panel);
       HgVcs myVcs = HgVcs.getInstance(myProject);
-      if (myVcs != null && !myVcs.getVersion().isAmendSupported()) {
-        myAmend.setEnabled(false);
-      }
+      myAmend.setEnabled(myVcs != null && myVcs.getVersion().isAmendSupported());
     }
 
+    @Override
     public void refresh() {
       super.refresh();
       myNextCommitAmend = false;
     }
 
+    @Override
     public void saveState() {
       myNextCommitAmend = myAmend.isSelected();
     }
 
+    @Override
     public void restoreState() {
       myNextCommitAmend = false;
     }
 
     @NotNull
     @Override
-    protected Collection<VirtualFile> getRoots() {
-      return HgUtil.getHgRepositories(myProject);
+    protected Set<VirtualFile> getVcsRoots(@NotNull Collection<FilePath> filePaths) {
+      return HgUtil.hgRoots(myProject, filePaths);
     }
 
     @Nullable
+    @Override
     protected String getLastCommitMessage(@NotNull VirtualFile repo) throws VcsException {
       HgCommandExecutor commandExecutor = new HgCommandExecutor(myProject);
       List<String> args = new ArrayList<String>();
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgHeadMerger.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgHeadMerger.java
index 15ab366..a9df96b 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgHeadMerger.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgHeadMerger.java
@@ -15,8 +15,6 @@
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vcs.history.VcsRevisionNumber;
-import com.intellij.openapi.vcs.update.UpdatedFiles;
 import com.intellij.openapi.vfs.VirtualFile;
 import org.jetbrains.annotations.NotNull;
 import org.zmlx.hg4idea.command.HgMergeCommand;
@@ -38,11 +36,9 @@
     this.hgMergeCommand = hgMergeCommand;
   }
 
-  public HgCommandResult merge(VirtualFile repo, UpdatedFiles updatedFiles,
-    VcsRevisionNumber revisionNumber) throws VcsException {
+  public HgCommandResult merge(VirtualFile repo) throws VcsException {
 
     HgCommandResult commandResult = ensureSuccess(hgMergeCommand.execute());
-
     try {
       HgUtil.markDirectoryDirty(project, repo);
     }
@@ -61,5 +57,4 @@
     LOG.info(msg, e);
     throw new VcsException(msg);
   }
-
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java
index b0b4c7a..355405f 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java
@@ -113,7 +113,7 @@
         abortOnMultiplePulledHeads(pulledBranchHeads);
         abortOnMultipleLocalHeads(remainingOriginalBranchHeads);
 
-        HgCommandResult mergeResult = doMerge(updatedFiles, indicator, pulledBranchHeads.get(0));
+        HgCommandResult mergeResult = doMerge(indicator);
 
         if (shouldCommitAfterMerge()) {
           commitOrWarnAboutConflicts(warnings, mergeResult);
@@ -198,15 +198,13 @@
       }
     }
 
-  private HgCommandResult doMerge(UpdatedFiles updatedFiles,
-                                  ProgressIndicator indicator,
-                                  HgRevisionNumber headToMerge) throws VcsException {
+  private HgCommandResult doMerge(ProgressIndicator indicator) throws VcsException {
     indicator.setText2(HgVcsMessages.message("hg4idea.update.progress.merging"));
     HgMergeCommand mergeCommand = new HgMergeCommand(project, repoRoot);
     //do not explicitly set the revision, that way mercurial itself checks that there are exactly
     //two heads in this branch
 //    mergeCommand.setRevision(headToMerge.getRevision());
-    return new HgHeadMerger(project, mergeCommand).merge(repoRoot, updatedFiles, headToMerge);
+    return new HgHeadMerger(project, mergeCommand).merge(repoRoot);
   }
 
   private void abortOnLocalChanges() throws VcsException {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java
index bef1b68..fb00361 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java
@@ -28,7 +28,7 @@
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgNameWithHashInfo;
 import org.zmlx.hg4idea.HgVcs;
-import org.zmlx.hg4idea.command.HgTagBranchCommand;
+import org.zmlx.hg4idea.command.HgBranchesCommand;
 import org.zmlx.hg4idea.execution.HgCommandResult;
 import org.zmlx.hg4idea.util.HgUtil;
 
@@ -162,13 +162,13 @@
     // Then blinking and do not work properly;
     if (!Disposer.isDisposed(getProject()) && !currentInfo.equals(myInfo)) {
       myInfo = currentInfo;
-      HgCommandResult branchCommandResult = new HgTagBranchCommand(getProject(), getRoot()).collectBranches();
+      HgCommandResult branchCommandResult = new HgBranchesCommand(getProject(), getRoot()).collectBranches();
       if (branchCommandResult == null || branchCommandResult.getExitValue() != 0) {
         LOG.warn("Could not collect hg opened branches."); // hg executable is not valid
         myOpenedBranches = myInfo.getBranches().keySet();
       }
       else {
-        myOpenedBranches = HgTagBranchCommand.collectNames(branchCommandResult);
+        myOpenedBranches = HgBranchesCommand.collectNames(branchCommandResult);
       }
       getProject().getMessageBus().syncPublisher(HgVcs.STATUS_TOPIC).update(getProject(), getRoot());
     }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.form
similarity index 90%
rename from plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.form
rename to plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.form
index 0fe5286..1e932fe 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.form
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.form
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.zmlx.hg4idea.ui.HgUpdateToDialog">
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.zmlx.hg4idea.ui.HgCommonDialogWithChoices">
   <grid id="27dc6" binding="contentPanel" layout-manager="GridLayoutManager" row-count="4" 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="500" height="400"/>
+      <xy x="22" y="20" width="498" height="291"/>
     </constraints>
     <properties/>
     <border type="none"/>
     <children>
       <vspacer id="84392">
         <constraints>
-          <grid row="3" 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="3" column="0" row-span="1" col-span="1" vsize-policy="2" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
         </constraints>
       </vspacer>
       <hspacer id="af9e5">
@@ -23,10 +23,14 @@
           <grid row="2" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
         </constraints>
         <properties>
+          <enabled value="false"/>
           <text value="&amp;Overwrite locally modified files (no backup)"/>
         </properties>
+        <clientProperties>
+          <html.disable class="java.lang.Boolean" value="false"/>
+        </clientProperties>
       </component>
-      <grid id="814c5" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+      <grid id="814c5" binding="myBranchesBorderPanel" layout-manager="GridLayoutManager" row-count="4" 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="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -35,7 +39,7 @@
         <clientProperties>
           <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
         </clientProperties>
-        <border type="none" title="Switch to"/>
+        <border type="none"/>
         <children>
           <component id="674b0" class="javax.swing.JRadioButton" binding="branchOption">
             <constraints>
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.java
new file mode 100644
index 0000000..4c7ff62
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCommonDialogWithChoices.java
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ * 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 org.zmlx.hg4idea.ui;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.ValidationInfo;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.repo.HgRepository;
+import org.zmlx.hg4idea.util.HgUtil;
+
+import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Collection;
+
+public class HgCommonDialogWithChoices extends DialogWrapper {
+
+
+  private JPanel contentPanel;
+  private JRadioButton branchOption;
+  private JRadioButton revisionOption;
+  private JRadioButton tagOption;
+  private JRadioButton bookmarkOption;
+  private JTextField revisionTxt;
+  protected JCheckBox cleanCbx;
+  private JComboBox branchSelector;
+  private JComboBox tagSelector;
+  private JComboBox bookmarkSelector;
+  protected HgRepositorySelectorComponent hgRepositorySelectorComponent;
+  protected JPanel myBranchesBorderPanel;
+
+  public HgCommonDialogWithChoices(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
+    super(project, false);
+    hgRepositorySelectorComponent.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        updateRepository();
+      }
+    });
+
+    ChangeListener changeListener = new ChangeListener() {
+      public void stateChanged(ChangeEvent e) {
+        update();
+      }
+    };
+    branchOption.addChangeListener(changeListener);
+    tagOption.addChangeListener(changeListener);
+    bookmarkOption.addChangeListener(changeListener);
+    revisionOption.addChangeListener(changeListener);
+    cleanCbx.setVisible(false);
+    setRoots(repositories, selectedRepo);
+    init();
+  }
+
+  public void setRoots(Collection<HgRepository> repos,
+                       @Nullable HgRepository selectedRepo) {
+    hgRepositorySelectorComponent.setRoots(repos);
+    hgRepositorySelectorComponent.setSelectedRoot(selectedRepo);
+    updateRepository();
+  }
+
+  public HgRepository getRepository() {
+    return hgRepositorySelectorComponent.getRepository();
+  }
+
+  public String getTag() {
+    return (String)tagSelector.getSelectedItem();
+  }
+
+  public boolean isTagSelected() {
+    return tagOption.isSelected();
+  }
+
+  public String getBranch() {
+    return (String)branchSelector.getSelectedItem();
+  }
+
+  public boolean isBranchSelected() {
+    return branchOption.isSelected();
+  }
+
+  public String getBookmark() {
+    return (String)bookmarkSelector.getSelectedItem();
+  }
+
+  public boolean isBookmarkSelected() {
+    return bookmarkOption.isSelected();
+  }
+
+  public String getRevision() {
+    return revisionTxt.getText();
+  }
+
+  private void update() {
+    revisionTxt.setEnabled(revisionOption.isSelected());
+    branchSelector.setEnabled(branchOption.isSelected());
+    tagSelector.setEnabled(tagOption.isSelected());
+    bookmarkSelector.setEnabled(bookmarkOption.isSelected());
+  }
+
+  private void updateRepository() {
+    HgRepository repo = hgRepositorySelectorComponent.getRepository();
+    branchSelector.setModel(new DefaultComboBoxModel(repo.getOpenedBranches().toArray()));
+    DefaultComboBoxModel tagComboBoxModel = new DefaultComboBoxModel(HgUtil.getNamesWithoutHashes(repo.getTags()).toArray());
+    tagComboBoxModel.addElement("tip");    //HgRepository does not store 'tip' tag because it is internal and not included in tags file
+    tagSelector.setModel(tagComboBoxModel);
+    bookmarkSelector.setModel(new DefaultComboBoxModel(HgUtil.getNamesWithoutHashes(repo.getBookmarks()).toArray()));
+    update();
+  }
+
+  protected JComponent createCenterPanel() {
+    return contentPanel;
+  }
+
+  @Override
+  protected String getDimensionServiceKey() {
+    return getClass().getName();
+  }
+
+  protected void createUIComponents() {
+  }
+
+  public String getTargetValue() {
+    return isBranchSelected() ? getBranch() : isBookmarkSelected() ? getBookmark() : isTagSelected() ? getTag() : getRevision();
+  }
+
+  protected ValidationInfo doValidate() {
+    String message = "You have to specify appropriate name or revision.";
+    return StringUtil.isEmptyOrSpaces(getTargetValue()) ? new ValidationInfo(message, myBranchesBorderPanel) : null;
+  }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.form
deleted file mode 100644
index 5a9411c..0000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.form
+++ /dev/null
@@ -1,139 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.zmlx.hg4idea.ui.HgMergeDialog">
-  <grid id="27dc6" binding="contentPanel" layout-manager="GridLayoutManager" row-count="3" 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="500" height="400"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <grid id="a0d6" 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>
-          <grid row="1" 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/>
-        <clientProperties>
-          <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
-        </clientProperties>
-        <border type="none" title="Merge with"/>
-        <children>
-          <component id="99075" class="javax.swing.JRadioButton" binding="branchOption">
-            <constraints>
-              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <selected value="true"/>
-              <text value="&amp;Branch"/>
-            </properties>
-          </component>
-          <component id="653f0" class="javax.swing.JRadioButton" binding="tagOption">
-            <constraints>
-              <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <text value="&amp;Tag"/>
-            </properties>
-          </component>
-          <component id="cefd6" class="javax.swing.JComboBox" binding="branchSelector">
-            <constraints>
-              <grid row="1" 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>
-              <enabled value="true"/>
-              <font name="Monospaced"/>
-            </properties>
-          </component>
-          <component id="e6ad1" class="javax.swing.JComboBox" binding="tagSelector">
-            <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>
-              <enabled value="false"/>
-              <font name="Monospaced"/>
-            </properties>
-          </component>
-          <hspacer id="2892f">
-            <constraints>
-              <grid row="5" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-            </constraints>
-          </hspacer>
-          <component id="f1e00" class="javax.swing.JTextField" binding="revisionTxt">
-            <constraints>
-              <grid row="4" 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>
-              <enabled value="false"/>
-            </properties>
-          </component>
-          <component id="f198c" class="javax.swing.JRadioButton" binding="revisionOption">
-            <constraints>
-              <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <selected value="false"/>
-              <text value="&amp;Revision"/>
-            </properties>
-          </component>
-          <component id="8ad2b" class="javax.swing.JRadioButton" binding="otherHeadRadioButton" default-binding="true">
-            <constraints>
-              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <selected value="false"/>
-              <text value="&amp;Other head:"/>
-              <toolTipText value="There is exactly one other head on this branch"/>
-            </properties>
-          </component>
-          <component id="10618" class="javax.swing.JLabel" binding="otherHeadLabel">
-            <constraints>
-              <grid row="0" column="1" 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=""/>
-            </properties>
-          </component>
-          <component id="dc07f" class="javax.swing.JRadioButton" binding="bookmarkOption">
-            <constraints>
-              <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-            </constraints>
-            <properties>
-              <text value="Book&amp;mark"/>
-            </properties>
-          </component>
-          <component id="14e6b" class="javax.swing.JComboBox" binding="bookmarkSelector">
-            <constraints>
-              <grid row="3" 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>
-              <enabled value="false"/>
-              <font name="Monospaced"/>
-            </properties>
-          </component>
-        </children>
-      </grid>
-      <vspacer id="fe9e6">
-        <constraints>
-          <grid row="2" 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>
-      <nested-form id="8b57e" form-file="org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.form" binding="hgRepositorySelectorComponent">
-        <constraints>
-          <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-        </constraints>
-      </nested-form>
-    </children>
-  </grid>
-  <buttonGroups>
-    <group name="mergeTarget">
-      <member id="f198c"/>
-      <member id="99075"/>
-      <member id="653f0"/>
-      <member id="8ad2b"/>
-      <member id="dc07f"/>
-    </group>
-  </buttonGroups>
-</form>
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java
index f41972a..259fe11 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java
@@ -12,181 +12,27 @@
 // limitations under the License.
 package org.zmlx.hg4idea.ui;
 
-import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ui.UIUtil;
+import com.intellij.ui.IdeBorderFactory;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.HgRevisionNumber;
-import org.zmlx.hg4idea.command.HgHeadsCommand;
-import org.zmlx.hg4idea.command.HgTagBranch;
-import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand;
-import org.zmlx.hg4idea.util.HgBranchesAndTags;
-import org.zmlx.hg4idea.util.HgUiUtil;
+import org.zmlx.hg4idea.repo.HgRepository;
 
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
 
-public class HgMergeDialog extends DialogWrapper {
+public class HgMergeDialog extends HgCommonDialogWithChoices {
 
-  private final Project project;
-
-  private JRadioButton revisionOption;
-  private JTextField revisionTxt;
-  private JRadioButton branchOption;
-  private JRadioButton tagOption;
-  private JRadioButton bookmarkOption;
-  private JComboBox branchSelector;
-  private JComboBox tagSelector;
-  private JComboBox bookmarkSelector;
-  private JPanel contentPanel;
-  private HgRepositorySelectorComponent hgRepositorySelectorComponent;
-  private JRadioButton otherHeadRadioButton;
-  private JLabel otherHeadLabel;
-
-  private HgRevisionNumber otherHead;
-  private Map<VirtualFile, Collection<HgTagBranch>> branchesForRepos;
-  private Map<VirtualFile, Collection<HgTagBranch>> tagsForRepos;
-  private Map<VirtualFile, Collection<HgTagBranch>> bookmarksForRepos;
-
-  public HgMergeDialog(Project project,
-                       Collection<VirtualFile> roots,
-                       @Nullable VirtualFile selectedRepo, HgBranchesAndTags branchesAndTags) {
-    super(project, false);
-    this.project = project;
-    branchesForRepos = branchesAndTags.getBranchesForRepos();
-    tagsForRepos = branchesAndTags.getTagsForRepos();
-    bookmarksForRepos = branchesAndTags.getBookmarksForRepos();
-    setRoots(roots, selectedRepo);
+  public HgMergeDialog(@NotNull Project project,
+                       @NotNull Collection<HgRepository> repositories,
+                       @Nullable HgRepository selectedRepo) {
+    super(project, repositories, selectedRepo);
     hgRepositorySelectorComponent.setTitle("Select repository to merge");
-    hgRepositorySelectorComponent.addActionListener(new ActionListener() {
-      public void actionPerformed(ActionEvent e) {
-        updateRepository();
-      }
-    });
-
-    ChangeListener changeListener = new ChangeListener() {
-      public void stateChanged(ChangeEvent e) {
-        updateOptions();
-      }
-    };
-    branchOption.addChangeListener(changeListener);
-    tagOption.addChangeListener(changeListener);
-    bookmarkOption.addChangeListener(changeListener);
-    revisionOption.addChangeListener(changeListener);
-    otherHeadRadioButton.addChangeListener(changeListener);
+    myBranchesBorderPanel.setBorder(IdeBorderFactory.createTitledBorder("Merge with", true));
     setTitle("Merge");
-    init();
-  }
-
-  public void setRoots(Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
-    hgRepositorySelectorComponent.setRoots(repos);
-    hgRepositorySelectorComponent.setSelectedRoot(selectedRepo);
-    updateRepository();
-  }
-
-  public VirtualFile getRepository() {
-    return hgRepositorySelectorComponent.getRepository();
-  }
-
-  public HgTagBranch getBranch() {
-    return branchOption.isSelected() ? (HgTagBranch) branchSelector.getSelectedItem() : null;
-  }
-
-  public HgTagBranch getTag() {
-    return tagOption.isSelected() ? (HgTagBranch) tagSelector.getSelectedItem() : null;
-  }
-
-  public HgTagBranch getBookmark() {
-    return bookmarkOption.isSelected() ? (HgTagBranch)bookmarkSelector.getSelectedItem() : null;
-  }
-
-  public String getRevision() {
-    return revisionOption.isSelected() ? revisionTxt.getText() : null;
-  }
-
-  public HgRevisionNumber getOtherHead() {
-    return otherHeadRadioButton.isSelected() ? otherHead : null;
-  }
-
-  private void updateRepository() {
-    VirtualFile repo = getRepository();
-    HgUiUtil.loadContentToDialog(repo, branchesForRepos, branchSelector);
-    HgUiUtil.loadContentToDialog(repo, tagsForRepos, tagSelector);
-    HgUiUtil.loadContentToDialog(repo, bookmarksForRepos, bookmarkSelector);
-    loadHeads(repo);
-  }
-
-  private void updateOptions() {
-    revisionTxt.setEnabled(revisionOption.isSelected());
-    branchSelector.setEnabled(branchOption.isSelected());
-    tagSelector.setEnabled(tagOption.isSelected());
-    bookmarkSelector.setEnabled(bookmarkOption.isSelected());
-  }
-
-  private void loadHeads(final VirtualFile root) {
-    ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
-      @Override
-      public void run() {
-        final List<HgRevisionNumber> heads = new HgHeadsCommand(project, root).execute();
-        if (heads.size() != 2) {
-          disableOtherHeadsChoice();
-          return;
-        }
-
-        HgRevisionNumber currentParent = new HgWorkingCopyRevisionsCommand(project).identify(root).getFirst();
-        for (Iterator<HgRevisionNumber> it = heads.iterator(); it.hasNext(); ) {
-          final HgRevisionNumber rev = it.next();
-          if (rev.getRevisionNumber().equals(currentParent.getRevisionNumber())) {
-            it.remove();
-          }
-        }
-
-        if (heads.size() == 1) {
-          UIUtil.invokeLaterIfNeeded(new Runnable() {
-            @Override
-            public void run() {
-              otherHeadRadioButton.setVisible(true);
-              otherHeadLabel.setVisible(true);
-              otherHead = heads.get(0);
-              otherHeadLabel.setText("  " + otherHead.asString());
-            }
-          });
-        }
-        else {
-          //apparently we are not at one of the heads
-          disableOtherHeadsChoice();
-        }
-      }
-    });
-  }
-
-  private void disableOtherHeadsChoice() {
-    UIUtil.invokeLaterIfNeeded(new Runnable() {
-      @Override
-      public void run() {
-        otherHeadLabel.setVisible(false);
-        otherHeadRadioButton.setVisible(false);
-      }
-    });
-  }
-
-  @Nullable
-  @Override
-  protected JComponent createCenterPanel() {
-    return contentPanel;
   }
 
   @Override
-  protected String getDimensionServiceKey() {
-    return getClass().getName();
+  protected String getHelpId() {
+    return "reference.mercurial.merge.dialog";
   }
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java
index 5b4af4a..2729817 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java
@@ -23,8 +23,10 @@
 import com.intellij.ui.EditorComboBox;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgRememberedInputs;
+import org.zmlx.hg4idea.repo.HgRepository;
 import org.zmlx.hg4idea.util.HgUtil;
 
 import javax.swing.*;
@@ -40,7 +42,7 @@
   private EditorComboBox myRepositoryURL;
   private String myCurrentRepositoryUrl;
 
-  public HgPullDialog(Project project) {
+  public HgPullDialog(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable final HgRepository selectedRepo) {
     super(project, false);
     this.project = project;
     hgRepositorySelector.setTitle("Select repository to pull changesets for");
@@ -53,6 +55,7 @@
     setTitle("Pull");
     setOKButtonText("Pull");
     init();
+    setRoots(repositories, selectedRepo);
   }
 
   public void createUIComponents() {
@@ -67,7 +70,7 @@
     });
   }
 
-  private void addPathsFromHgrc(VirtualFile repo) {
+  private void addPathsFromHgrc(@NotNull VirtualFile repo) {
     Collection<String> paths = HgUtil.getRepositoryPaths(project, repo);
     for (String path : paths) {
       myRepositoryURL.prependItem(path);
@@ -80,15 +83,15 @@
   }
 
   public VirtualFile getRepository() {
-    return hgRepositorySelector.getRepository();
+    return hgRepositorySelector.getRepository().getRoot();
   }
 
   public String getSource() {
     return myCurrentRepositoryUrl;
   }
 
-  public void setRoots(Collection<VirtualFile> repos, @Nullable final VirtualFile selectedRepo) {
-    hgRepositorySelector.setRoots(repos);
+  private void setRoots(@NotNull Collection<HgRepository> repositories, @Nullable final HgRepository selectedRepo) {
+    hgRepositorySelector.setRoots(repositories);
     hgRepositorySelector.setSelectedRoot(selectedRepo);
     onChangeRepository();
   }
@@ -106,8 +109,8 @@
     ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
       @Override
       public void run() {
-        final VirtualFile repo = hgRepositorySelector.getRepository();
-        final String defaultPath = HgUtil.getRepositoryDefaultPath(project,repo);
+        final VirtualFile repo = hgRepositorySelector.getRepository().getRoot();
+        final String defaultPath = HgUtil.getRepositoryDefaultPath(project, repo);
         if (!StringUtil.isEmptyOrSpaces(defaultPath)) {
           UIUtil.invokeAndWaitIfNeeded(new Runnable() {
             @Override
@@ -133,5 +136,4 @@
   protected String getDimensionServiceKey() {
     return HgPullDialog.class.getName();
   }
-
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.form
index a11d251..ab1fd73 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.form
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.form
@@ -3,7 +3,7 @@
   <grid id="27dc6" binding="contentPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
     <margin top="0" left="0" bottom="0" right="0"/>
     <constraints>
-      <xy x="20" y="20" width="529" height="307"/>
+      <xy x="3" y="20" width="546" height="397"/>
     </constraints>
     <properties/>
     <border type="none"/>
@@ -18,13 +18,13 @@
         <children>
           <vspacer id="f51de">
             <constraints>
-              <grid row="4" 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="4" column="0" row-span="1" col-span="1" vsize-policy="2" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
             </constraints>
           </vspacer>
-          <grid id="3b42" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+          <grid id="3b42" layout-manager="GridLayoutManager" row-count="3" column-count="3" 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="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+              <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
                 <minimum-size width="-1" height="100"/>
               </grid>
             </constraints>
@@ -34,17 +34,9 @@
             </clientProperties>
             <border type="etched" title="Options"/>
             <children>
-              <component id="e40ef" class="javax.swing.JCheckBox" binding="revisionCbx">
-                <constraints>
-                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-                </constraints>
-                <properties>
-                  <text value="&amp;Revision:"/>
-                </properties>
-              </component>
               <component id="8b024" class="javax.swing.JTextField" binding="revisionTxt">
                 <constraints>
-                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
+                  <grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
                     <preferred-size width="150" height="-1"/>
                   </grid>
                 </constraints>
@@ -55,45 +47,76 @@
               </component>
               <hspacer id="27a66">
                 <constraints>
-                  <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                  <grid row="2" column="1" row-span="1" col-span="2" vsize-policy="1" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                 </constraints>
               </hspacer>
+              <grid id="3c96d" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+                <margin top="0" left="0" bottom="0" right="0"/>
+                <constraints>
+                  <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties/>
+                <border type="etched" title="Branch Options"/>
+                <children>
+                  <component id="1adc4" class="javax.swing.JComboBox" binding="branchComboBox">
+                    <constraints>
+                      <grid row="0" column="1" row-span="1" col-span="2" vsize-policy="4" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties/>
+                  </component>
+                  <component id="e6341" class="javax.swing.JCheckBox" binding="branchCheckBox" default-binding="true">
+                    <constraints>
+                      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <text resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.push.branch"/>
+                    </properties>
+                  </component>
+                  <component id="e76b" class="javax.swing.JCheckBox" binding="newBranchCheckBox">
+                    <constraints>
+                      <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <enabled value="false"/>
+                      <horizontalAlignment value="0"/>
+                      <horizontalTextPosition value="11"/>
+                      <text resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.push.asNewBranch"/>
+                    </properties>
+                  </component>
+                  <component id="131ed" class="javax.swing.JComboBox" binding="myBookmarkComboBox">
+                    <constraints>
+                      <grid row="2" column="1" row-span="1" col-span="2" vsize-policy="4" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <editable value="true"/>
+                    </properties>
+                  </component>
+                  <component id="a621e" class="javax.swing.JCheckBox" binding="myBookmarkCheckBox">
+                    <constraints>
+                      <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <text resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.push.bookmark"/>
+                    </properties>
+                  </component>
+                </children>
+              </grid>
+              <component id="e40ef" class="javax.swing.JCheckBox" binding="revisionCbx">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <text value="&amp;Revision:"/>
+                </properties>
+              </component>
               <component id="5fcc4" class="javax.swing.JCheckBox" binding="forceCheckBox" default-binding="true">
                 <constraints>
-                  <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                  <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
                 </constraints>
                 <properties>
                   <text resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.push.force"/>
                 </properties>
               </component>
-              <component id="e6341" class="javax.swing.JCheckBox" binding="branchCheckBox" default-binding="true">
-                <constraints>
-                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-                </constraints>
-                <properties>
-                  <text resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.push.branch"/>
-                </properties>
-              </component>
-              <component id="1adc4" class="javax.swing.JComboBox" binding="branchComboBox">
-                <constraints>
-                  <grid row="1" 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="e76b" class="javax.swing.JCheckBox" binding="newBranchCheckBox">
-                <constraints>
-                  <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-                </constraints>
-                <properties>
-                  <enabled value="false"/>
-                  <text resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.push.asNewBranch"/>
-                </properties>
-              </component>
-              <hspacer id="af930">
-                <constraints>
-                  <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
-                </constraints>
-              </hspacer>
             </children>
           </grid>
           <nested-form id="9e17d" form-file="org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.form" binding="hgRepositorySelectorComponent">
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java
index 7660494..892bbb9 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java
@@ -13,8 +13,6 @@
 package org.zmlx.hg4idea.ui;
 
 import com.intellij.dvcs.DvcsRememberedInputs;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.editor.event.DocumentAdapter;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
@@ -24,10 +22,9 @@
 import com.intellij.util.ArrayUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.HgPusher;
 import org.zmlx.hg4idea.HgRememberedInputs;
 import org.zmlx.hg4idea.HgVcsMessages;
-import org.zmlx.hg4idea.command.HgTagBranch;
+import org.zmlx.hg4idea.repo.HgRepository;
 import org.zmlx.hg4idea.util.HgUtil;
 
 import javax.swing.*;
@@ -38,7 +35,6 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.Collection;
-import java.util.List;
 
 public class HgPushDialog extends DialogWrapper {
 
@@ -53,9 +49,11 @@
   private JComboBox branchComboBox;
   private EditorComboBox myRepositoryURL;
   private JCheckBox newBranchCheckBox;
+  private JComboBox myBookmarkComboBox;
+  private JCheckBox myBookmarkCheckBox;
   private String myCurrentRepositoryUrl;
 
-  public HgPushDialog(Project project, Collection<VirtualFile> repos, List<HgTagBranch> branches, @Nullable VirtualFile selectedRepo) {
+  public HgPushDialog(Project project, Collection<HgRepository> repos, @Nullable HgRepository selectedRepo) {
     super(project, false);
     myProject = project;
 
@@ -69,15 +67,22 @@
     final UpdatingListener updatingListener = new UpdatingListener();
     revisionCbx.addChangeListener(updatingListener);
     branchCheckBox.addChangeListener(updatingListener);
+    myBookmarkCheckBox.addChangeListener(updatingListener);
     revisionTxt.getDocument().addDocumentListener(updatingListener);
 
     setTitle(HgVcsMessages.message("hg4idea.push.dialog.title"));
     setOKButtonText("Push");
     init();
 
+    setRoots(repos, selectedRepo);
+  }
+
+  private void setRoots(@NotNull Collection<HgRepository> repos,
+                        @Nullable HgRepository selectedRepo) {
     hgRepositorySelectorComponent.setRoots(repos);
     hgRepositorySelectorComponent.setSelectedRoot(selectedRepo);
-    updateBranchComboBox(branches);
+    HgRepository repo = hgRepositorySelectorComponent.getRepository();
+    updateComboBoxes(repo);
     updateRepository();
   }
 
@@ -101,10 +106,12 @@
     }
   }
 
-  public VirtualFile getRepository() {
+  @NotNull
+  public HgRepository getRepository() {
     return hgRepositorySelectorComponent.getRepository();
   }
 
+  @NotNull
   public String getTarget() {
     return myCurrentRepositoryUrl;
   }
@@ -115,8 +122,13 @@
   }
 
   @Nullable
-  public HgTagBranch getBranch() {
-    return branchCheckBox.isSelected() ? (HgTagBranch) branchComboBox.getSelectedItem() : null;
+  public String getBranch() {
+    return branchCheckBox.isSelected() ? (String)branchComboBox.getSelectedItem() : null;
+  }
+
+  @Nullable
+  public String getBookmarkName() {
+    return myBookmarkCheckBox.isSelected() ? (String)myBookmarkComboBox.getSelectedItem() : null;
   }
 
   public boolean isForce() {
@@ -124,8 +136,8 @@
   }
 
   public boolean isNewBranch() {
-      return newBranchCheckBox.isSelected();
-    }
+    return newBranchCheckBox.isSelected();
+  }
 
   protected JComponent createCenterPanel() {
     return contentPanel;
@@ -137,25 +149,21 @@
   }
 
   public void updateRepository() {
-    ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
-      @Override
-      public void run() {
-        final VirtualFile repo = hgRepositorySelectorComponent.getRepository();
-        final String defaultPath = HgUtil.getRepositoryDefaultPushPath(myProject, repo);
-        final List<HgTagBranch> branches = HgPusher.getBranches(myProject, repo);
-        ApplicationManager.getApplication().invokeLater(new Runnable() {
-          @Override
-          public void run() {
-            addPathsFromHgrc(repo);
-            if (defaultPath != null) {
-              updateRepositoryUrlText(HgUtil.removePasswordIfNeeded(defaultPath));
-              myCurrentRepositoryUrl = defaultPath;
-            }
-            updateBranchComboBox(branches);
-          }
-        }, ModalityState.stateForComponent(getRootPane()));
-      }
-    });
+    HgRepository repo = hgRepositorySelectorComponent.getRepository();
+    String defaultPath = HgUtil.getRepositoryDefaultPushPath(repo);
+    addPathsFromHgrc(repo.getRoot());
+    if (defaultPath != null) {
+      updateRepositoryUrlText(HgUtil.removePasswordIfNeeded(defaultPath));
+      myCurrentRepositoryUrl = defaultPath;
+    }
+    updateComboBoxes(repo);
+  }
+
+  private void updateComboBoxes(HgRepository repo) {
+    final Collection<String> branches = repo.getOpenedBranches();
+    final Collection<String> bookmarkNames = HgUtil.getNamesWithoutHashes(repo.getBookmarks());
+    branchComboBox.setModel(new DefaultComboBoxModel(branches.toArray()));
+    myBookmarkComboBox.setModel(new DefaultComboBoxModel(bookmarkNames.toArray()));
   }
 
   private void updateRepositoryUrlText(String defaultPath) {
@@ -165,15 +173,12 @@
     }
   }
 
-  private void updateBranchComboBox(@NotNull List<HgTagBranch> branches) {
-    branchComboBox.setModel(new DefaultComboBoxModel(branches.toArray()));
-  }
-
   private void update() {
     setOKActionEnabled(validateOptions());
     revisionTxt.setEnabled(revisionCbx.isSelected());
     branchComboBox.setEnabled(branchCheckBox.isSelected());
     newBranchCheckBox.setEnabled(branchCheckBox.isSelected());
+    myBookmarkComboBox.setEnabled(myBookmarkCheckBox.isSelected());
   }
 
   private boolean validateOptions() {
@@ -213,5 +218,4 @@
       update();
     }
   }
-
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.java
index 89fc834..edc2fb0 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.java
@@ -12,10 +12,10 @@
 // limitations under the License.
 package org.zmlx.hg4idea.ui;
 
-import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.IdeBorderFactory;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.repo.HgRepository;
 
 import javax.swing.*;
 import java.awt.event.ActionListener;
@@ -25,54 +25,31 @@
   private JComboBox repositorySelector;
   private JPanel mainPanel;
 
-  public void setRoots(Collection<VirtualFile> roots) {
+  public void setRoots(Collection<HgRepository> roots) {
     DefaultComboBoxModel model = new DefaultComboBoxModel();
-    for (VirtualFile repo : roots) {
-      model.addElement(new RepositoryDisplay(repo));
+    for (HgRepository repo : roots) {
+      model.addElement(repo);
     }
     repositorySelector.setModel(model);
     mainPanel.setVisible(roots.size() > 1);
   }
 
-  public void setSelectedRoot(@Nullable VirtualFile repository) {
+  public void setSelectedRoot(@Nullable HgRepository repository) {
     if (repository != null) {
-      repositorySelector.setSelectedItem(new RepositoryDisplay(repository));
+      repositorySelector.setSelectedItem(repository);
     }
   }
 
-  public void addActionListener(ActionListener actionListener) {
+  public void addActionListener(@NotNull ActionListener actionListener) {
     repositorySelector.addActionListener(actionListener);
   }
 
-  public void setTitle(String title) {
+  public void setTitle(@NotNull String title) {
     mainPanel.setBorder(IdeBorderFactory.createTitledBorder(title, true));
   }
 
-  public VirtualFile getRepository() {
-    return ((RepositoryDisplay) repositorySelector.getSelectedItem()).repo;
+  @NotNull
+  public HgRepository getRepository() {
+    return (HgRepository)repositorySelector.getSelectedItem();
   }
-
-  private class RepositoryDisplay {
-    @NotNull private final VirtualFile repo;
-
-    public RepositoryDisplay(@NotNull VirtualFile repo) {
-      this.repo = repo;
-    }
-
-    @Override
-    public String toString() {
-      return repo.getPresentableUrl();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-      return obj instanceof RepositoryDisplay && this.repo.equals(((RepositoryDisplay)obj).repo);
-    }
-
-    @Override
-    public int hashCode() {
-      return repo.hashCode();
-    }
-  }
-
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRunConflictResolverDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRunConflictResolverDialog.java
index ca4ab00..0196bd4 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRunConflictResolverDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRunConflictResolverDialog.java
@@ -18,10 +18,12 @@
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.Consumer;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgFile;
 import org.zmlx.hg4idea.command.HgResolveCommand;
 import org.zmlx.hg4idea.command.HgResolveStatusEnum;
+import org.zmlx.hg4idea.repo.HgRepository;
 
 import javax.swing.*;
 import java.awt.event.ActionEvent;
@@ -37,7 +39,9 @@
 
   private final Project project;
 
-  public HgRunConflictResolverDialog(Project project) {
+  public HgRunConflictResolverDialog(@NotNull Project project,
+                                     @NotNull Collection<HgRepository> repositories,
+                                     @Nullable HgRepository selectedRepo) {
     super(project, false);
     this.project = project;
     repositorySelector.addActionListener(new ActionListener() {
@@ -47,14 +51,16 @@
     });
     setTitle("Resolve Conflicts");
     init();
+    setRoots(repositories, selectedRepo);
   }
 
-  public VirtualFile getRepository() {
+  @NotNull
+  public HgRepository getRepository() {
     return repositorySelector.getRepository();
   }
 
-  public void setRoots(Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
-    repositorySelector.setRoots(repos);
+  private void setRoots(@NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
+    repositorySelector.setRoots(repositories);
     repositorySelector.setSelectedRoot(selectedRepo);
     onChangeRepository();
   }
@@ -64,7 +70,7 @@
   }
 
   private void onChangeRepository() {
-    VirtualFile repo = repositorySelector.getRepository();
+    VirtualFile repo = repositorySelector.getRepository().getRoot();
     HgResolveCommand command = new HgResolveCommand(project);
     final ModalityState modalityState = ApplicationManager.getApplication().getModalityStateForComponent(getRootPane());
     command.list(repo, new Consumer<Map<HgFile, HgResolveStatusEnum>>() {
@@ -90,5 +96,4 @@
       }
     });
   }
-
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java
index 02e3e8d..ba90007 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java
@@ -16,7 +16,9 @@
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.repo.HgRepository;
 
 import javax.swing.*;
 import javax.swing.event.DocumentEvent;
@@ -29,7 +31,7 @@
   private JTextField tagTxt;
   private HgRepositorySelectorComponent hgRepositorySelectorComponent;
 
-  public HgTagDialog(Project project) {
+  public HgTagDialog(@NotNull Project project, @NotNull Collection<HgRepository> repos, @Nullable HgRepository selectedRepo) {
     super(project, false);
     hgRepositorySelectorComponent.setTitle("Select repository to tag");
     DocumentListener documentListener = new DocumentListener() {
@@ -50,6 +52,8 @@
 
     setTitle("Tag");
     init();
+
+    setRoots(repos, selectedRepo);
   }
 
   public String getTagName() {
@@ -57,10 +61,10 @@
   }
 
   public VirtualFile getRepository() {
-    return hgRepositorySelectorComponent.getRepository();
+    return hgRepositorySelectorComponent.getRepository().getRoot();
   }
 
-  public void setRoots(Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
+  private void setRoots(@NotNull Collection<HgRepository> repos, @Nullable HgRepository selectedRepo) {
     hgRepositorySelectorComponent.setRoots(repos);
     hgRepositorySelectorComponent.setSelectedRoot(selectedRepo);
     update();
@@ -77,5 +81,4 @@
   private boolean validateOptions() {
     return !StringUtil.isEmptyOrSpaces(tagTxt.getText());
   }
-
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.java
index d6638dd..c0b6607 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.java
@@ -13,141 +13,30 @@
 package org.zmlx.hg4idea.ui;
 
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.IdeBorderFactory;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.command.HgTagBranch;
-import org.zmlx.hg4idea.util.HgBranchesAndTags;
-import org.zmlx.hg4idea.util.HgUiUtil;
+import org.zmlx.hg4idea.repo.HgRepository;
 
-import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.util.Collection;
-import java.util.Map;
 
-public class HgUpdateToDialog extends DialogWrapper {
+public class HgUpdateToDialog extends HgCommonDialogWithChoices {
 
-  private final Project project;
-
-  private JPanel contentPanel;
-  private JRadioButton branchOption;
-  private JRadioButton revisionOption;
-  private JRadioButton tagOption;
-  private JRadioButton bookmarkOption;
-  private JTextField revisionTxt;
-  private JCheckBox cleanCbx;
-  private JComboBox branchSelector;
-  private JComboBox tagSelector;
-  private JComboBox bookmarkSelector;
-  private HgRepositorySelectorComponent hgRepositorySelectorComponent;
-  @NotNull private Map<VirtualFile, Collection<HgTagBranch>> branchesForRepos;
-  @NotNull private Map<VirtualFile, Collection<HgTagBranch>> tagsForRepos;
-  @NotNull private Map<VirtualFile, Collection<HgTagBranch>> bookmarksForRepos;
-
-  public HgUpdateToDialog(Project project) {
-    super(project, false);
-    this.project = project;
+  public HgUpdateToDialog(Project project, @NotNull Collection<HgRepository> repos, @Nullable HgRepository selectedRepo) {
+    super(project, repos, selectedRepo);
+    myBranchesBorderPanel.setBorder(IdeBorderFactory.createTitledBorder("Switch to", true));
     hgRepositorySelectorComponent.setTitle("Select repository to switch");
-    hgRepositorySelectorComponent.addActionListener(new ActionListener() {
-      public void actionPerformed(ActionEvent e) {
-        updateRepository();
-      }
-    });
-
-    ChangeListener changeListener = new ChangeListener() {
-      public void stateChanged(ChangeEvent e) {
-        update();
-      }
-    };
-    branchOption.addChangeListener(changeListener);
-    tagOption.addChangeListener(changeListener);
-    bookmarkOption.addChangeListener(changeListener);
-    revisionOption.addChangeListener(changeListener);
-
-    setTitle("Switch working directory");
-    init();
-  }
-
-  public void setRoots(Collection<VirtualFile> repos,
-                       @Nullable VirtualFile selectedRepo, HgBranchesAndTags branchesAndTags) {
-    hgRepositorySelectorComponent.setRoots(repos);
-    branchesForRepos = branchesAndTags.getBranchesForRepos();
-    tagsForRepos = branchesAndTags.getTagsForRepos();
-    bookmarksForRepos = branchesAndTags.getBookmarksForRepos();
-    hgRepositorySelectorComponent.setSelectedRoot(selectedRepo);
-    updateRepository();
-  }
-
-  public VirtualFile getRepository() {
-    return hgRepositorySelectorComponent.getRepository();
-  }
-
-  public HgTagBranch getTag() {
-    return (HgTagBranch) tagSelector.getSelectedItem();
-  }
-
-  public boolean isTagSelected() {
-    return tagOption.isSelected();
-  }
-
-  public HgTagBranch getBranch() {
-    return (HgTagBranch) branchSelector.getSelectedItem();
-  }
-
-  public boolean isBranchSelected() {
-    return branchOption.isSelected();
-  }
-
-  public HgTagBranch getBookmark() {
-    return (HgTagBranch)bookmarkSelector.getSelectedItem();
-  }
-
-  public boolean isBookmarkSelected() {
-    return bookmarkOption.isSelected();
-  }
-
-  public String getRevision() {
-    return revisionTxt.getText();
-  }
-
-  public boolean isRevisionSelected() {
-    return revisionOption.isSelected();
+    setTitle("Switch Working Directory");
+    cleanCbx.setVisible(true);
+    cleanCbx.setEnabled(true);
   }
 
   public boolean isRemoveLocalChanges() {
     return cleanCbx.isSelected();
   }
 
-  private void update() {
-    revisionTxt.setEnabled(revisionOption.isSelected());
-    branchSelector.setEnabled(branchOption.isSelected());
-    tagSelector.setEnabled(tagOption.isSelected());
-    bookmarkSelector.setEnabled(bookmarkOption.isSelected());
-  }
-
-  private void updateRepository() {
-    VirtualFile repo = hgRepositorySelectorComponent.getRepository();
-    HgUiUtil.loadContentToDialog(repo, branchesForRepos, branchSelector);
-    HgUiUtil.loadContentToDialog(repo, tagsForRepos, tagSelector);
-    HgUiUtil.loadContentToDialog(repo, bookmarksForRepos, bookmarkSelector);
-    update();
-  }
-
-  protected JComponent createCenterPanel() {
-    return contentPanel;
-  }
-
   @Override
   protected String getHelpId() {
     return "reference.mercurial.switch.working.directory";
   }
-
-  @Override
-  protected String getDimensionServiceKey() {
-    return getClass().getName();
-  }
 }
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgBranchesAndTags.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgBranchesAndTags.java
deleted file mode 100644
index 08d7141..0000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgBranchesAndTags.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.zmlx.hg4idea.util;
-
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NotNull;
-import org.zmlx.hg4idea.command.HgTagBranch;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * @author Nadya Zabrodina
- */
-
-public class HgBranchesAndTags {
-
-  @NotNull private final Map<VirtualFile, Collection<HgTagBranch>> branchesForRepos = ContainerUtil.newHashMap();
-  @NotNull private final Map<VirtualFile, Collection<HgTagBranch>> tagsForRepos = ContainerUtil.newHashMap();
-  @NotNull private final Map<VirtualFile, Collection<HgTagBranch>> bookmarks = ContainerUtil.newHashMap();
-
-  @NotNull
-  public Map<VirtualFile, Collection<HgTagBranch>> getBranchesForRepos() {
-    return branchesForRepos;
-  }
-
-  public void addBranches(@NotNull VirtualFile repo, @NotNull Collection<HgTagBranch> branches) {
-    branchesForRepos.put(repo, branches);
-  }
-
-  @NotNull
-  public Map<VirtualFile, Collection<HgTagBranch>> getTagsForRepos() {
-    return tagsForRepos;
-  }
-
-  public void addTags(@NotNull VirtualFile repo, @NotNull Collection<HgTagBranch> tags) {
-    tagsForRepos.put(repo, tags);
-  }
-
-  @NotNull
-  public Map<VirtualFile, Collection<HgTagBranch>> getBookmarksForRepos() {
-    return bookmarks;
-  }
-
-  public void addBookmarks(@NotNull VirtualFile repo, @NotNull Collection<HgTagBranch> tags) {
-    bookmarks.put(repo, tags);
-  }
-}
\ No newline at end of file
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUiUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUiUtil.java
deleted file mode 100644
index 6d806b3..0000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUiUtil.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.zmlx.hg4idea.util;
-
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.Task;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Consumer;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.HgVcsMessages;
-import org.zmlx.hg4idea.action.HgCommandResultNotifier;
-import org.zmlx.hg4idea.command.HgTagBranch;
-import org.zmlx.hg4idea.command.HgTagBranchCommand;
-import org.zmlx.hg4idea.execution.HgCommandResult;
-
-import javax.swing.*;
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * @author Nadya Zabrodina
- */
-public class HgUiUtil {
-
-  public static void loadBranchesInBackgroundableAndExecuteAction(@NotNull final Project project,
-                                                                  @NotNull final Collection<VirtualFile> repos,
-                                                                  @NotNull final Consumer<HgBranchesAndTags> successHandler) {
-    final HgBranchesAndTags branchTagInfo = new HgBranchesAndTags();
-    new Task.Backgroundable(project, "Collecting information...") {
-      @Override
-      public void run(@NotNull ProgressIndicator indicator) {
-        for (final VirtualFile repo : repos) {
-          HgTagBranchCommand tagBranchCommand = new HgTagBranchCommand(project, repo);
-          HgCommandResult result = tagBranchCommand.collectBranches();
-          if (result == null) {
-            indicator.cancel();
-            return;
-          }
-          branchTagInfo.addBranches(repo, HgTagBranchCommand.parseResult(result));
-          result = tagBranchCommand.collectTags();
-          if (result == null) {
-            indicator.cancel();
-            return;
-          }
-          branchTagInfo.addTags(repo, HgTagBranchCommand.parseResult(result));
-
-          result = tagBranchCommand.collectBookmarks();
-          if (result == null) {
-            indicator.cancel();
-            return;
-          }
-          branchTagInfo.addBookmarks(repo, HgTagBranchCommand.parseResult(result));
-        }
-      }
-
-      @Override
-      public void onCancel() {
-        new HgCommandResultNotifier(project)
-          .notifyError(null, "Mercurial command failed", HgVcsMessages.message("hg4idea.branches.error.description"));
-      }
-
-      @Override
-      public void onSuccess() {
-        successHandler.consume(branchTagInfo);
-      }
-    }.queue();
-  }
-
-  public static void loadContentToDialog(@Nullable VirtualFile root, @NotNull Map<VirtualFile, Collection<HgTagBranch>> contentMap,
-                                         @NotNull JComboBox selector) {
-    assert contentMap.get(root) != null : "No information about root " + root;
-    selector.setModel(new DefaultComboBoxModel(contentMap.get(root).toArray()));
-  }
-}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
index fd0fc50..ee7f1b4 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
@@ -40,6 +40,7 @@
 import com.intellij.openapi.wm.WindowManager;
 import com.intellij.openapi.wm.impl.status.StatusBarUtil;
 import com.intellij.ui.GuiUtils;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.vcsUtil.VcsUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -241,6 +242,21 @@
   }
 
   /**
+   * Get hg roots for paths
+   *
+   * @param filePaths the context paths
+   * @return a set of hg roots
+   */
+  @NotNull
+  public static Set<VirtualFile> hgRoots(@NotNull Project project, @NotNull Collection<FilePath> filePaths) {
+    HashSet<VirtualFile> roots = new HashSet<VirtualFile>();
+    for (FilePath path : filePaths) {
+      ContainerUtil.addIfNotNull(roots, getHgRootOrNull(project, path));
+    }
+    return roots;
+  }
+
+  /**
    * Gets the Mercurial root for the given file path or null if non exists:
    * the root should not only be in directory mappings, but also the .hg repository folder should exist.
    * @see #getHgRootOrThrow(com.intellij.openapi.project.Project, com.intellij.openapi.vcs.FilePath)
@@ -596,6 +612,11 @@
   }
 
   @Nullable
+  public static String getRepositoryDefaultPushPath(@NotNull HgRepository repository) {
+    return repository.getRepositoryConfig().getDefaultPushPath();
+  }
+
+  @Nullable
   public static String getConfig(@NotNull Project project,
                                  @NotNull VirtualFile root,
                                  @NotNull String section,
@@ -646,6 +667,7 @@
         names.add(hash.getName());
       }
     }
+    Collections.sort(names);
     return names;
   }
 
diff --git a/plugins/javaFX/FxBuilderEmbedder/FxBuilderEmbedder.iml b/plugins/javaFX/FxBuilderEmbedder/FxBuilderEmbedder.iml
index 94b91b5..2a19b78 100644
--- a/plugins/javaFX/FxBuilderEmbedder/FxBuilderEmbedder.iml
+++ b/plugins/javaFX/FxBuilderEmbedder/FxBuilderEmbedder.iml
@@ -17,6 +17,7 @@
         <SOURCES />
       </library>
     </orderEntry>
+    <orderEntry type="module" module-name="javaFX" />
   </component>
 </module>
 
diff --git a/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar b/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar
index 10561a4..e853e97 100644
--- a/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar
+++ b/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar
Binary files differ
diff --git a/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java b/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java
index 6748c07..65b1557 100644
--- a/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java
+++ b/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java
@@ -5,7 +5,10 @@
 import com.oracle.javafx.scenebuilder.kit.editor.panel.hierarchy.treeview.HierarchyTreeViewController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.inspector.InspectorPanelController;
 import com.oracle.javafx.scenebuilder.kit.editor.panel.library.LibraryPanelController;
-import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument;
+import com.oracle.javafx.scenebuilder.kit.editor.selection.AbstractSelectionGroup;
+import com.oracle.javafx.scenebuilder.kit.editor.selection.ObjectSelectionGroup;
+import com.oracle.javafx.scenebuilder.kit.fxom.*;
+import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName;
 import javafx.application.Platform;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
@@ -17,6 +20,7 @@
 
 import javax.swing.*;
 import java.net.URL;
+import java.util.*;
 
 /**
  * @author Alexander Lobas
@@ -26,8 +30,10 @@
   private final EditorCallback myEditorCallback;
   private final JFXPanel myPanel = new JFXPanel();
   private EditorController myEditorController;
-  private ChangeListener<Number> myListener;
   private volatile boolean mySkipChanges;
+  private ChangeListener<Number> myListener;
+  private ChangeListener<Number> mySelectionListener;
+  private final Map<String, int[][]> mySelectionState = new FixedHashMap<String, int[][]>(16);
 
   public SceneBuilderImpl(URL url, EditorCallback editorCallback) {
     myFileURL = url;
@@ -80,7 +86,6 @@
       Platform.runLater(new Runnable() {
         @Override
         public void run() {
-          // TODO: restore state
           loadFile();
         }
       });
@@ -96,13 +101,26 @@
         }
       }
     };
+    mySelectionListener = new ChangeListener<Number>() {
+      @Override
+      public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
+        if (!mySkipChanges) {
+          int[][] state = getSelectionState();
+          if (state != null) {
+            mySelectionState.put(myEditorController.getFxmlText(), state);
+          }
+        }
+      }
+    };
 
     myEditorController.getJobManager().revisionProperty().addListener(myListener);
+    myEditorController.getSelection().revisionProperty().addListener(mySelectionListener);
   }
 
   @Override
   public void close() {
     if (myEditorController != null) {
+      myEditorController.getSelection().revisionProperty().removeListener(mySelectionListener);
       myEditorController.getJobManager().revisionProperty().removeListener(myListener);
     }
   }
@@ -113,6 +131,11 @@
     try {
       String fxmlText = FXOMDocument.readContentFromURL(myFileURL);
       myEditorController.setFxmlTextAndLocation(fxmlText, myFileURL);
+
+      int[][] selectionState = mySelectionState.get(fxmlText);
+      if (selectionState != null) {
+        restoreSelection(selectionState);
+      }
     }
     catch (Throwable e) {
       myEditorCallback.handleError(e);
@@ -121,4 +144,133 @@
       mySkipChanges = false;
     }
   }
+
+  private int[][] getSelectionState() {
+    AbstractSelectionGroup group = myEditorController.getSelection().getGroup();
+    if (group instanceof ObjectSelectionGroup) {
+      Set<FXOMObject> items = ((ObjectSelectionGroup)group).getItems();
+      int[][] state = new int[items.size()][];
+      int index = 0;
+
+      for (FXOMObject item : items) {
+        IntArrayList path = new IntArrayList();
+        componentToPath(item, path);
+        state[index++] = path.toArray();
+      }
+
+      return state;
+    }
+
+    return null;
+  }
+
+  private static void componentToPath(FXOMObject component, IntArrayList path) {
+    FXOMObject parent = component.getParentObject();
+
+    if (parent != null) {
+      path.add(0, component.getParentProperty().getValues().indexOf(component));
+      componentToPath(parent, path);
+    }
+  }
+
+  private void restoreSelection(int[][] state) {
+    Collection<FXOMObject> newSelection = new ArrayList<FXOMObject>();
+    FXOMObject rootComponent = myEditorController.getFxomDocument().getFxomRoot();
+
+    for (int[] path : state) {
+      pathToComponent(newSelection, rootComponent, path, 0);
+    }
+
+    myEditorController.getSelection().select(newSelection);
+  }
+
+  private static void pathToComponent(Collection<FXOMObject> components, FXOMObject component, int[] path, int index) {
+    if (index == path.length) {
+      components.add(component);
+    }
+    else {
+      List<FXOMObject> children = Collections.emptyList();
+      Map<PropertyName, FXOMProperty> properties = ((FXOMInstance)component).getProperties();
+      for (Map.Entry<PropertyName, FXOMProperty> entry : properties.entrySet()) {
+        FXOMProperty value = entry.getValue();
+        if (value instanceof FXOMPropertyC) {
+          children = ((FXOMPropertyC)value).getValues();
+          break;
+        }
+      }
+
+      int componentIndex = path[index];
+      if (0 <= componentIndex && componentIndex < children.size()) {
+        pathToComponent(components, children.get(componentIndex), path, index + 1);
+      }
+    }
+  }
+
+  private static class FixedHashMap<K, V> extends HashMap<K, V> {
+    private final int mySize;
+    private final List<K> myKeys = new LinkedList<K>();
+
+    public FixedHashMap(int size) {
+      mySize = size;
+    }
+
+    @Override
+    public V put(K key, V value) {
+      if (!myKeys.contains(key)) {
+        if (myKeys.size() >= mySize) {
+          remove(myKeys.remove(0));
+        }
+        myKeys.add(key);
+      }
+      return super.put(key, value);
+    }
+
+    @Override
+    public V get(Object key) {
+      if (myKeys.contains(key)) {
+        int index = myKeys.indexOf(key);
+        int last = myKeys.size() - 1;
+        myKeys.set(index, myKeys.get(last));
+        myKeys.set(last, (K)key);
+      }
+      return super.get(key);
+    }
+  }
+
+  private static final int[] EMPTY_INTS = new int[0];
+
+  private static class IntArrayList {
+    private int[] myData = EMPTY_INTS;
+    private int mySize;
+
+    public void add(int index, int element) {
+      if (index > mySize || index < 0) {
+        throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize);
+      }
+
+      ensureCapacity(mySize + 1);
+      System.arraycopy(myData, index, myData, index + 1, mySize - index);
+      myData[index] = element;
+      mySize++;
+    }
+
+    public void ensureCapacity(int minCapacity) {
+      int oldCapacity = myData.length;
+      if (minCapacity > oldCapacity) {
+        int[] oldData = myData;
+        int newCapacity = oldCapacity * 3 / 2 + 1;
+        if (newCapacity < minCapacity) {
+          newCapacity = minCapacity;
+        }
+        myData = new int[newCapacity];
+        System.arraycopy(oldData, 0, myData, 0, mySize);
+      }
+    }
+
+    public int[] toArray() {
+      int[] result = new int[mySize];
+      System.arraycopy(myData, 0, result, 0, mySize);
+      return result;
+    }
+  }
 }
\ No newline at end of file
diff --git a/plugins/javaFX/javaFX-CE/src/META-INF/plugin.xml b/plugins/javaFX/javaFX-CE/src/META-INF/plugin.xml
index e037210..6b65da2 100644
--- a/plugins/javaFX/javaFX-CE/src/META-INF/plugin.xml
+++ b/plugins/javaFX/javaFX-CE/src/META-INF/plugin.xml
@@ -4,7 +4,17 @@
   <version>1.0</version>
   <vendor>JetBrains</vendor>
   <description>
-    This plugin provides JavaFX2 support.
-  </description>
+      <![CDATA[
+      This plugin enables <a href="http://www.oracle.com/technetwork/java/javafx/overview/index.html">JavaFX</a> support.
+      The following features are available:
+        <ul>
+        <li>Dedicated file type.</li>
+        <li>Ability to create a project with the special file and directory structure.</li>
+        <li>JavaFX-aware coding assistance (code completion, search, navigation and refactoring in JavaFX-specific source files).</li>
+        <li>Integration with <a href="http://www.oracle.com/technetwork/java/javafx/tools/index.html">JavaFX Scene Builder</a>.</li>
+        <li>JavaFX application packaging capabilities.</li>
+        </ul>
+      ]]>
+   </description>
   <xi:include href="/META-INF/common-javaFX-plugin.xml" xpointer="xpointer(/idea-plugin/*)"/>
 </idea-plugin>
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataExternalizer.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataExternalizer.java
index 2de1bc6..384d085 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataExternalizer.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataExternalizer.java
@@ -16,6 +16,7 @@
 package org.jetbrains.plugins.javaFX;
 
 import com.intellij.util.io.DataExternalizer;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -29,7 +30,7 @@
 */
 public class FxmlDataExternalizer implements DataExternalizer<Set<String>> {
   @Override
-  public void save(DataOutput out, Set<String> value) throws IOException {
+  public void save(@NotNull DataOutput out, Set<String> value) throws IOException {
     out.writeInt(value.size());
     for (String s : value) {
       out.writeUTF(s);
@@ -37,7 +38,7 @@
   }
 
   @Override
-  public Set<String> read(DataInput in) throws IOException {
+  public Set<String> read(@NotNull DataInput in) throws IOException {
     final int size = in.readInt();
     final Set<String> result = new HashSet<String>(size);
 
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxControllerClassIndex.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxControllerClassIndex.java
index 1caf0a0..e5c3915 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxControllerClassIndex.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxControllerClassIndex.java
@@ -58,11 +58,13 @@
     return myDataIndexer;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<String> getKeyDescriptor() {
     return myKeyDescriptor;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return myInputFilter;
@@ -133,7 +135,7 @@
       super(StdFileTypes.XML);
     }
     @Override
-    public boolean acceptInput(final VirtualFile file) {
+    public boolean acceptInput(@NotNull final VirtualFile file) {
       return JavaFxFileTypeFactory.isFxml(file);
     }
   }
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxCustomComponentsIndex.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxCustomComponentsIndex.java
index 50c8b84..2178fd8 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxCustomComponentsIndex.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxCustomComponentsIndex.java
@@ -81,11 +81,13 @@
     return myDataIndexer;
   }
 
+  @NotNull
   @Override
   public DataExternalizer<Set<String>> getValueExternalizer() {
     return myDataExternalizer;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return myInputFilter;
@@ -97,6 +99,7 @@
     return KEY;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<String> getKeyDescriptor() {
     return myKeyDescriptor;
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxIdsIndex.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxIdsIndex.java
index e0fe90a..fcaaada 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxIdsIndex.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxIdsIndex.java
@@ -42,11 +42,13 @@
     return myDataIndexer;
   }
 
+  @NotNull
   @Override
   public DataExternalizer<Set<String>> getValueExternalizer() {
     return myDataExternalizer;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return myInputFilter;
@@ -58,6 +60,7 @@
     return KEY;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<String> getKeyDescriptor() {
     return myKeyDescriptor;
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
index de123d1..6ea5c51 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
@@ -27,7 +27,7 @@
   public boolean accept(@NotNull Project project, @NotNull VirtualFile file) {
     return JavaFxFileTypeFactory.FXML_EXTENSION.equalsIgnoreCase(file.getExtension()) &&
            SystemInfo.isJavaVersionAtLeast("1.8") &&
-           Registry.is("embed.scene.builder", false);
+           Registry.is("embed.scene.builder", true);
   }
 
   @NotNull
diff --git a/plugins/junit/src/META-INF/plugin.xml b/plugins/junit/src/META-INF/plugin.xml
index d023807..969fec8 100644
--- a/plugins/junit/src/META-INF/plugin.xml
+++ b/plugins/junit/src/META-INF/plugin.xml
@@ -16,7 +16,18 @@
 
 <idea-plugin>
   <name>JUnit</name>
-  <description>Provides possibility to run JUnit 3.x and 4.x tests and view their results</description>
+  <description>
+      <![CDATA[
+      This plugin supports <a href="https://github.com/junit-team/junit">JUnit tests</a>.
+      The following features are available:
+        <ul>
+        <li>Ability to create JUnit 3.x or JUnit 4.x tests.</li>
+        <li>Navigation between a test and test subject.</li>
+        <li>Running tests.</li>
+        <li>Viewing test results in the dedicated Test Runner tab of the Run tool window.</li>
+        </ul>
+      ]]>
+   </description>
   <version>1.0</version>
   <vendor>JetBrains</vendor>
   <extensions defaultExtensionNs="com.intellij">
diff --git a/plugins/maven/jps-plugin/maven-jps-plugin.iml b/plugins/maven/jps-plugin/maven-jps-plugin.iml
index 8098c4c..f601ed3 100644
--- a/plugins/maven/jps-plugin/maven-jps-plugin.iml
+++ b/plugins/maven/jps-plugin/maven-jps-plugin.iml
@@ -22,6 +22,7 @@
         <SOURCES />
       </library>
     </orderEntry>
+    <orderEntry type="module" module-name="jps-serialization-tests" scope="TEST" />
   </component>
 </module>
 
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java
index 8fe4348..0c4be99 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java
@@ -29,7 +29,8 @@
   void customize(@Nullable MavenWorkspaceMap workspaceMap,
                  boolean failOnUnresolvedDependency,
                  @NotNull MavenServerConsole console,
-                 @NotNull MavenServerProgressIndicator indicator) throws RemoteException;
+                 @NotNull MavenServerProgressIndicator indicator,
+                 boolean alwaysUpdateSnapshots) throws RemoteException;
 
   @NotNull
   MavenServerExecutionResult resolveProject(@NotNull File file,
diff --git a/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java b/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java
index 630e664..7ed82b0 100644
--- a/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java
+++ b/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java
@@ -586,7 +586,8 @@
   public void customize(@Nullable MavenWorkspaceMap workspaceMap,
                         boolean failOnUnresolvedDependency,
                         @NotNull MavenServerConsole console,
-                        @NotNull MavenServerProgressIndicator indicator) {
+                        @NotNull MavenServerProgressIndicator indicator,
+                        boolean alwaysUpdateSnapshots) {
     try {
       ((CustomArtifactFactory)getComponent(ArtifactFactory.class)).customize();
       ((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).customize();
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java
index ae45421..ded8fa3 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java
@@ -111,6 +111,8 @@
 
   private Date myBuildStartTime;
 
+  private boolean myAlwaysUpdateSnapshots;
+
   public Maven3ServerEmbedderImpl(MavenServerSettings settings) throws RemoteException {
     File mavenHome = settings.getMavenHome();
     if (mavenHome != null) {
@@ -269,7 +271,8 @@
   public void customize(@Nullable MavenWorkspaceMap workspaceMap,
                         boolean failOnUnresolvedDependency,
                         @NotNull MavenServerConsole console,
-                        @NotNull MavenServerProgressIndicator indicator) throws RemoteException {
+                        @NotNull MavenServerProgressIndicator indicator,
+                        boolean alwaysUpdateSnapshots) throws RemoteException {
 
     try {
       ((CustomMaven3ArtifactFactory)getComponent(ArtifactFactory.class)).customize();
@@ -281,6 +284,8 @@
 
       myBuildStartTime = new Date();
 
+      myAlwaysUpdateSnapshots = alwaysUpdateSnapshots;
+
       setConsoleAndIndicator(console, new MavenServerProgressIndicatorWrapper(indicator));
     }
     catch (Exception e) {
@@ -349,6 +354,8 @@
     final MavenExecutionRequest request =
       createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
 
+    request.setUpdateSnapshots(myAlwaysUpdateSnapshots);
+
     final AtomicReference<MavenExecutionResult> ref = new AtomicReference<MavenExecutionResult>();
 
     executeWithMavenSession(request, new Runnable() {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateManagedDependencyAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateManagedDependencyAction.java
index 18250c3..93af00a 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateManagedDependencyAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateManagedDependencyAction.java
@@ -78,10 +78,16 @@
                 dependency.getGroupId().setStringValue(groupId);
                 dependency.getArtifactId().setStringValue(artifactId);
                 String typeValue = parentDependency.getType().getStringValue();
+                String classifier = parentDependency.getClassifier().getStringValue();
 
                 if (!StringUtil.isEmptyOrSpaces(typeValue)) {
                   dependency.getType().setStringValue(typeValue);
                 }
+
+                if (!StringUtil.isEmptyOrSpaces(classifier)) {
+                  dependency.getClassifier().setStringValue(classifier);
+                }
+
                 dependency.getVersion().undefine();
               }
             }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java
index 614332f..e809208 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -666,14 +666,14 @@
   }
 
   private static class SetDescriptor implements DataExternalizer<Set<String>> {
-    public void save(DataOutput s, Set<String> set) throws IOException {
+    public void save(@NotNull DataOutput s, Set<String> set) throws IOException {
       s.writeInt(set.size());
       for (String each : set) {
         s.writeUTF(each);
       }
     }
 
-    public Set<String> read(DataInput s) throws IOException {
+    public Set<String> read(@NotNull DataInput s) throws IOException {
       int count = s.readInt();
       Set<String> result = new THashSet<String>(count);
       while (count-- > 0) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
index 4089981..0019d59 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
@@ -1206,7 +1206,7 @@
                       @NotNull ResolveContext context,
                       @NotNull MavenProgressIndicator process) throws MavenProcessCanceledException {
     MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE);
-    embedder.customizeForResolve(getWorkspaceMap(), console, process);
+    embedder.customizeForResolve(getWorkspaceMap(), console, process, generalSettings.isAlwaysUpdateSnapshots());
 
     try {
       process.checkCanceled();
@@ -1321,7 +1321,7 @@
                                   @NotNull MavenProgressIndicator process,
                                   @NotNull EmbedderTask task) throws MavenProcessCanceledException {
     MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(embedderKind);
-    embedder.customizeForResolve(getWorkspaceMap(), console, process);
+    embedder.customizeForResolve(getWorkspaceMap(), console, process, false);
     embedder.clearCachesFor(mavenProject.getMavenId());
     try {
       task.run(embedder);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RemoveManagedFilesAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RemoveManagedFilesAction.java
index 12cdead..33889ee 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RemoveManagedFilesAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RemoveManagedFilesAction.java
@@ -20,34 +20,20 @@
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.idea.maven.project.MavenProject;
 import org.jetbrains.idea.maven.project.MavenProjectsManager;
 import org.jetbrains.idea.maven.utils.MavenUtil;
 import org.jetbrains.idea.maven.utils.actions.MavenAction;
 import org.jetbrains.idea.maven.utils.actions.MavenActionUtil;
 
+import java.util.ArrayList;
 import java.util.List;
 
 public class RemoveManagedFilesAction extends MavenAction {
   @Override
   protected boolean isAvailable(AnActionEvent e) {
     if (!super.isAvailable(e)) return false;
-
-    List<VirtualFile> files = MavenActionUtil.getMavenProjectsFiles(e.getDataContext());
-    if (files.isEmpty()) return false;
-
-    return files.size() == 1 || isAllFilesAreManaged(MavenActionUtil.getProjectsManager(e.getDataContext()), files);
-  }
-
-  private static boolean isAllFilesAreManaged(@NotNull MavenProjectsManager projectsManager, List<VirtualFile> files) {
-    for (VirtualFile file : files) {
-      if (!projectsManager.isManagedFile(file)) {
-        return false;
-      }
-    }
-
-    return true;
+    return MavenActionUtil.getMavenProjectsFiles(e.getDataContext()).size() > 0;
   }
 
   @Override
@@ -57,34 +43,47 @@
     MavenProjectsManager projectsManager = MavenActionUtil.getProjectsManager(context);
 
     List<VirtualFile> selectedFiles = MavenActionUtil.getMavenProjectsFiles(context);
-    if (selectedFiles.size() != 1) return;
+    List<VirtualFile> removableFiles = new ArrayList<VirtualFile>();
 
-    VirtualFile pomXml = selectedFiles.get(0);
-
-    if (!projectsManager.isManagedFile(pomXml)) {
-      MavenProject mavenProject = projectsManager.findProject(pomXml);
-      assert mavenProject != null;
-
-      String aggregatorDescription = "";
-
-      MavenProject aggregator = projectsManager.findAggregator(mavenProject);
-
-      if (aggregator != null) {
-        aggregatorDescription = " (" + aggregator.getMavenId().getDisplayString() + ')';
+    for (VirtualFile pomXml : selectedFiles) {
+      if (projectsManager.isManagedFile(pomXml)) {
+        removableFiles.add(pomXml);
       }
+      else {
+        notifyUserIfNeeded(context, projectsManager, selectedFiles, pomXml);
+      }
+    }
+    projectsManager.removeManagedFiles(removableFiles);
+  }
 
-      Notification notification = new Notification(MavenUtil.MAVEN_NOTIFICATION_GROUP, "Failed to remove project",
-                                                   "You can not remove selected project because it's " +
-                                                   "imported as a module of another project" +
-                                                   aggregatorDescription
-                                                   +". You can use Ignore action. Only root project can be removed.",
-                                                   NotificationType.ERROR);
+  private static void notifyUserIfNeeded(DataContext context,
+                                         MavenProjectsManager projectsManager,
+                                         List<VirtualFile> selectedFiles,
+                                         VirtualFile pomXml) {
+    MavenProject mavenProject = projectsManager.findProject(pomXml);
+    assert mavenProject != null;
 
-      notification.setImportant(true);
-      notification.notify(MavenActionUtil.getProject(context));
-      return;
+    MavenProject aggregator = projectsManager.findAggregator(mavenProject);
+    while (aggregator != null && !projectsManager.isManagedFile(aggregator.getFile())) {
+      aggregator = projectsManager.findAggregator(aggregator);
     }
 
-    projectsManager.removeManagedFiles(selectedFiles);
+    if (aggregator != null && !selectedFiles.contains(aggregator.getFile())) {
+      notifyUser(context, mavenProject, aggregator);
+    }
   }
-}
+
+  private static void notifyUser(DataContext context, MavenProject mavenProject, MavenProject aggregator) {
+    String aggregatorDescription = " (" + aggregator.getMavenId().getDisplayString() + ')';
+    Notification notification = new Notification(MavenUtil.MAVEN_NOTIFICATION_GROUP, "Failed to remove project",
+                                                 "You can not remove " + mavenProject.getName() + " because it's " +
+                                                 "imported as a module of another project" +
+                                                 aggregatorDescription
+                                                 + ". You can use Ignore action. Only root project can be removed.",
+                                                 NotificationType.ERROR
+    );
+
+    notification.setImportant(true);
+    notification.notify(MavenActionUtil.getProject(context));
+  }
+}
\ No newline at end of file
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java
index c5ac93c..a0882e7 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java
@@ -49,7 +49,7 @@
   }
 
   public void customizeForResolve(MavenConsole console, MavenProgressIndicator indicator) {
-    setCustomization(console, indicator, null, false);
+    setCustomization(console, indicator, null, false, false);
     perform(new Retriable<Object>() {
       @Override
       public Object execute() throws RemoteException {
@@ -59,8 +59,8 @@
     });
   }
 
-  public void customizeForResolve(MavenWorkspaceMap workspaceMap, MavenConsole console, MavenProgressIndicator indicator) {
-    setCustomization(console, indicator, workspaceMap, false);
+  public void customizeForResolve(MavenWorkspaceMap workspaceMap, MavenConsole console, MavenProgressIndicator indicator, boolean alwaysUpdateSnapshot) {
+    setCustomization(console, indicator, workspaceMap, false, alwaysUpdateSnapshot);
     perform(new Retriable<Object>() {
       @Override
       public Object execute() throws RemoteException {
@@ -73,7 +73,7 @@
   public void customizeForStrictResolve(MavenWorkspaceMap workspaceMap,
                                         MavenConsole console,
                                         MavenProgressIndicator indicator) {
-    setCustomization(console, indicator, workspaceMap, true);
+    setCustomization(console, indicator, workspaceMap, true, false);
     perform(new Retriable<Object>() {
       @Override
       public Object execute() throws RemoteException {
@@ -87,7 +87,8 @@
     getOrCreateWrappee().customize(myCustomization.workspaceMap,
                                    myCustomization.failOnUnresolvedDependency,
                                    myCustomization.console,
-                                   myCustomization.indicator);
+                                   myCustomization.indicator,
+                                   myCustomization.alwaysUpdateSnapshot);
   }
 
   @NotNull
@@ -243,12 +244,14 @@
   private synchronized void setCustomization(MavenConsole console,
                                              MavenProgressIndicator indicator,
                                              MavenWorkspaceMap workspaceMap,
-                                             boolean failOnUnresolvedDependency) {
+                                             boolean failOnUnresolvedDependency,
+                                             boolean alwaysUpdateSnapshot) {
     resetCustomization();
     myCustomization = new Customization(MavenServerManager.wrapAndExport(console),
                                         MavenServerManager.wrapAndExport(indicator),
                                         workspaceMap,
-                                        failOnUnresolvedDependency);
+                                        failOnUnresolvedDependency,
+                                        alwaysUpdateSnapshot);
   }
 
   private synchronized void resetCustomization() {
@@ -276,15 +279,18 @@
 
     private final MavenWorkspaceMap workspaceMap;
     private final boolean failOnUnresolvedDependency;
+    private final boolean alwaysUpdateSnapshot;
 
     private Customization(MavenServerConsole console,
                           MavenServerProgressIndicator indicator,
                           MavenWorkspaceMap workspaceMap,
-                          boolean failOnUnresolvedDependency) {
+                          boolean failOnUnresolvedDependency,
+                          boolean alwaysUpdateSnapshot) {
       this.console = console;
       this.indicator = indicator;
       this.workspaceMap = workspaceMap;
       this.failOnUnresolvedDependency = failOnUnresolvedDependency;
+      this.alwaysUpdateSnapshot = alwaysUpdateSnapshot;
     }
   }
 }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenMergingUpdateQueue.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenMergingUpdateQueue.java
index cb9ec71..e988b98 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenMergingUpdateQueue.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenMergingUpdateQueue.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -78,7 +78,7 @@
     try {
       EditorEventMulticaster multicaster = EditorFactory.getInstance().getEventMulticaster();
 
-      multicaster.addCaretListener(new CaretListener() {
+      multicaster.addCaretListener(new CaretAdapter() {
           public void caretPositionChanged(CaretEvent e) {
             MavenMergingUpdateQueue.this.restartTimer();
           }
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/vfs/MavenPropertiesVirtualFile.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/vfs/MavenPropertiesVirtualFile.java
index 7a8ccb5..000b855 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/vfs/MavenPropertiesVirtualFile.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/vfs/MavenPropertiesVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -52,46 +52,57 @@
     return builder.toString().getBytes();
   }
 
+  @Override
   @NotNull
   public String getName() {
     return myPath;
   }
 
+  @Override
   @NotNull
   public VirtualFileSystem getFileSystem() {
     return myFS;
   }
 
+  @Override
+  @NotNull
   public String getPath() {
     return myPath;
   }
 
+  @Override
   public boolean isWritable() {
     return false;
   }
 
+  @Override
   public boolean isDirectory() {
     return false;
   }
 
+  @Override
   public boolean isValid() {
     return true;
   }
 
+  @Override
   public VirtualFile getParent() {
     return null;
   }
 
+  @Override
   public VirtualFile[] getChildren() {
     return null;
   }
 
+  @Override
   @NotNull
   public byte[] contentsToByteArray() throws IOException {
     if (myContent == null) throw new IOException();
     return myContent;
   }
 
+  @Override
   public long getTimeStamp() {
     return -1;
   }
@@ -101,17 +112,21 @@
     return myContent.hashCode();
   }
 
+  @Override
   public long getLength() {
     return myContent.length;
   }
 
+  @Override
   public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) {
   }
 
+  @Override
   public InputStream getInputStream() throws IOException {
     return VfsUtilCore.byteStreamSkippingBOM(myContent,this);
   }
 
+  @Override
   @NotNull
   public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
     throw new UnsupportedOperationException();
diff --git a/plugins/maven/src/main/resources/META-INF/plugin.xml b/plugins/maven/src/main/resources/META-INF/plugin.xml
index 337fe0c..5ef7e21 100644
--- a/plugins/maven/src/main/resources/META-INF/plugin.xml
+++ b/plugins/maven/src/main/resources/META-INF/plugin.xml
@@ -2,7 +2,21 @@
   <id>org.jetbrains.idea.maven</id>
 
   <name>Maven Integration</name>
-  <description>Import Maven projects and execute Maven goals</description>
+  <description>
+      <![CDATA[
+      This plugin provides <a href="http://maven.apache.org/">Maven</a> support.
+      The following features are available:
+        <ul>
+        <li>Maven Projects tool window.</li>
+        <li>Dedicated module type.</li>
+        <li>Maven repositories support.</li>
+        <li>Full editing support for pom.xml file.</li>
+        <li>Possibility to import Maven projects.</li>
+        <li>Running and debugging Maven goals.</li>
+        <li>Compiling.</li>
+        </ul>
+      ]]>
+   </description>
   <vendor>JetBrains</vendor>
 
   <extensionPoints>
diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesFileType.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesFileType.java
index 6d9d3ee..fb0f8d4 100644
--- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesFileType.java
+++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesFileType.java
@@ -63,12 +63,10 @@
 
   @Override
   public String getCharset(@NotNull VirtualFile file, final byte[] content) {
-    final EncodingRegistry encodingManager = EncodingRegistry.getInstance();
-    if (encodingManager != null) {
-      final Charset encoding = encodingManager.getEncoding(file, true);
-      if (encoding != null) return encoding.toString();
+    Charset charset = EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file);
+    if (charset == null) {
+      charset = CharsetToolkit.getDefaultSystemCharset();
     }
-    final Charset charset = CharsetToolkit.getDefaultSystemCharset();
-    return charset != null ? charset.toString() : null;
+    return charset != null ? charset.name() : null;
   }
 }
diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java
index 7a48ff9..f61c3b8 100644
--- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -42,15 +42,19 @@
     return myResourceBundle;
   }
 
+  @Override
   @NotNull
   public VirtualFileSystem getFileSystem() {
     return LocalFileSystem.getInstance();
   }
 
+  @Override
+  @NotNull
   public String getPath() {
     return getName();
   }
 
+  @Override
   @NotNull
   public String getName() {
     return myResourceBundle.getBaseName();
@@ -71,71 +75,88 @@
     return myResourceBundle.hashCode();
   }
 
+  @Override
   public void rename(Object requestor, @NotNull String newName) throws IOException {
   }
 
+  @Override
   public boolean isWritable() {
     return true;
   }
 
+  @Override
   public boolean isDirectory() {
     return false;
   }
 
+  @Override
   public boolean isValid() {
     return true;
   }
 
+  @Override
   public VirtualFile getParent() {
     return myResourceBundle.getBaseDirectory();
   }
 
+  @Override
   public VirtualFile[] getChildren() {
     return EMPTY_ARRAY;
   }
 
+  @Override
   public VirtualFile createChildDirectory(Object requestor, String name) throws IOException {
     throw new UnsupportedOperationException();
   }
 
+  @Override
   public VirtualFile createChildData(Object requestor, @NotNull String name) throws IOException {
     throw new UnsupportedOperationException();
   }
 
+  @Override
   public void delete(Object requestor) throws IOException {
     //todo
   }
 
+  @Override
   public void move(Object requestor, @NotNull VirtualFile newParent) throws IOException {
     //todo
   }
 
+  @Override
   public InputStream getInputStream() throws IOException {
     throw new UnsupportedOperationException();
   }
 
+  @Override
   @NotNull
   public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
     throw new UnsupportedOperationException();
   }
 
+  @Override
   @NotNull
   public byte[] contentsToByteArray() throws IOException {
     throw new UnsupportedOperationException();
   }
 
+  @Override
   public long getModificationStamp() {
     return 0;
   }
 
+  @Override
   public long getTimeStamp() {
     return 0;
   }
 
+  @Override
   public long getLength() {
     return 0;
   }
 
+  @Override
   public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) {
 
   }
diff --git a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java
index 370f07f..de96b39 100644
--- a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java
+++ b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.intellij.lang.properties.xml;
 
 import com.intellij.ide.highlighter.XmlFileType;
@@ -52,16 +67,19 @@
     return this;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<Key> getKeyDescriptor() {
     return this;
   }
 
+  @NotNull
   @Override
   public DataExternalizer<String> getValueExternalizer() {
     return ENUMERATOR_STRING_DESCRIPTOR;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return this;
@@ -78,7 +96,7 @@
   }
 
   @Override
-  public boolean acceptInput(VirtualFile file) {
+  public boolean acceptInput(@NotNull VirtualFile file) {
     return true;
   }
 
@@ -139,7 +157,7 @@
   private final byte[] buffer = IOUtil.allocReadWriteUTFBuffer();
 
   @Override
-  public void save(DataOutput out, Key value) throws IOException {
+  public void save(@NotNull DataOutput out, Key value) throws IOException {
     out.writeBoolean(value.isMarker);
     if (value.key != null) {
       IOUtil.writeUTFFast(buffer, out, value.key);
@@ -147,7 +165,7 @@
   }
 
   @Override
-  public Key read(DataInput in) throws IOException {
+  public Key read(@NotNull DataInput in) throws IOException {
     boolean isMarker = in.readBoolean();
     return isMarker ? MARKER_KEY : new Key(IOUtil.readUTFFast(buffer, in));
   }
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnLoadedBrachesStorage.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnLoadedBrachesStorage.java
index 8f6de1e..8fe1fa5 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnLoadedBrachesStorage.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnLoadedBrachesStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2011 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.
@@ -21,6 +21,7 @@
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.util.io.DataExternalizer;
 import com.intellij.util.io.EnumeratorStringDescriptor;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.branchConfig.InfoStorage;
 import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
@@ -99,7 +100,7 @@
   private DataExternalizer<Map<String, Collection<SvnBranchItem>>> createExternalizer() {
     return new DataExternalizer<Map<String, Collection<SvnBranchItem>>>() {
       @Override
-      public void save(DataOutput out, Map<String, Collection<SvnBranchItem>> value) throws IOException {
+      public void save(@NotNull DataOutput out, Map<String, Collection<SvnBranchItem>> value) throws IOException {
         out.writeInt(value.size());
         ArrayList<String> keys = new ArrayList<String>(value.keySet());
         Collections.sort(keys);
@@ -117,7 +118,7 @@
       }
 
       @Override
-      public Map<String, Collection<SvnBranchItem>> read(DataInput in) throws IOException {
+      public Map<String, Collection<SvnBranchItem>> read(@NotNull DataInput in) throws IOException {
         final HashMap<String, Collection<SvnBranchItem>> map = new HashMap<String, Collection<SvnBranchItem>>();
         int mapSize = in.readInt();
         for (int i = 0; i < mapSize; i++) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java
index 2fd8b8b..5d7bd6d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2010 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.
@@ -28,6 +28,7 @@
 import com.intellij.util.continuation.TaskDescriptor;
 import com.intellij.util.io.DataExternalizer;
 import com.intellij.util.io.EnumeratorStringDescriptor;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.idea.svn.SvnVcs;
 import org.jetbrains.idea.svn.history.CopyData;
@@ -88,7 +89,7 @@
   }
 
   private static class BranchDataExternalizer implements DataExternalizer<TreeMap<String,BranchCopyData>> {
-    public void save(DataOutput out, TreeMap<String,BranchCopyData> value) throws IOException {
+    public void save(@NotNull DataOutput out, TreeMap<String,BranchCopyData> value) throws IOException {
       out.writeInt(value.size());
       for (Map.Entry<String, BranchCopyData> entry : value.entrySet()) {
         out.writeUTF(entry.getKey());
@@ -100,7 +101,7 @@
       }
     }
 
-    public TreeMap<String,BranchCopyData> read(DataInput in) throws IOException {
+    public TreeMap<String,BranchCopyData> read(@NotNull DataInput in) throws IOException {
       final TreeMap<String,BranchCopyData> result = new TreeMap<String, BranchCopyData>();
 
       final int num = in.readInt();
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java
index 029b9a7..db609ab 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java
@@ -21,13 +21,15 @@
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.tasks.TaskManagerTestCase;
 import com.intellij.xdebugger.XDebuggerManager;
-import com.intellij.xdebugger.breakpoints.XBreakpoint;
 import com.intellij.xdebugger.breakpoints.XBreakpointManager;
 import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
+import com.intellij.xdebugger.breakpoints.XBreakpointType;
+import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
 import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointImpl;
 import org.intellij.plugins.xsltDebugger.XsltBreakpointType;
 
 import java.io.File;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -78,10 +80,12 @@
     final WorkingContextManager manager = getContextManager();
     final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(getProject()).getBreakpointManager();
 
+    final XsltBreakpointType type = XBreakpointType.EXTENSION_POINT_NAME.findExtension(XsltBreakpointType.class);
+
     ApplicationManager.getApplication().runWriteAction(new Runnable() {
       public void run() {
         XLineBreakpointImpl<XBreakpointProperties> breakpoint =
-          (XLineBreakpointImpl<XBreakpointProperties>)breakpointManager.addLineBreakpoint(new XsltBreakpointType(), "foo", 0, null);
+          (XLineBreakpointImpl<XBreakpointProperties>)breakpointManager.addLineBreakpoint(type, "foo", 0, null);
 
         final String name = "foo";
         manager.saveContext(name, null);
@@ -89,8 +93,8 @@
       }
     });
     manager.loadContext("foo");
-    XBreakpoint<?>[] breakpoints = breakpointManager.getAllBreakpoints();
-    assertEquals(1, breakpoints.length);
+    Collection<? extends XLineBreakpoint<XBreakpointProperties>> breakpoints = breakpointManager.getBreakpoints(type);
+    assertEquals(1, breakpoints.size());
     manager.clearContext();
   }
 
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java
index 0c34444..e9de7fb 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java
@@ -89,15 +89,16 @@
           @Override
           public void actionPerformed(AnActionEvent e) {
             if (e.getInputEvent() instanceof KeyEvent) {
-              action.update(e);
-              if (e.getPresentation().isEnabled()) {
-                action.actionPerformed(e);
+              AnActionEvent event = new AnActionEvent(e.getInputEvent(), e.getDataContext(), e.getPlace(), new Presentation(), e.getActionManager(), e.getModifiers());
+              action.update(event);
+              if (event.getPresentation().isEnabled()) {
+                action.actionPerformed(event);
               }
               else {
-                terminalPanel.handleKeyEvent((KeyEvent)e.getInputEvent());
+                terminalPanel.handleKeyEvent((KeyEvent)event.getInputEvent());
               }
 
-              e.getInputEvent().consume();
+              event.getInputEvent().consume();
             }
           }
         };
diff --git a/plugins/ui-designer-core/src/META-INF/DesignerCorePlugin.xml b/plugins/ui-designer-core/src/META-INF/DesignerCorePlugin.xml
new file mode 100644
index 0000000..ede0d2b
--- /dev/null
+++ b/plugins/ui-designer-core/src/META-INF/DesignerCorePlugin.xml
@@ -0,0 +1,19 @@
+<idea-plugin version="2">
+
+  <module value="com.intellij.ui-designer-new"/>
+
+  <depends>com.intellij.modules.lang</depends>
+
+  <project-components>
+    <component>
+      <implementation-class>com.intellij.designer.DesignerToolWindowManager</implementation-class>
+    </component>
+    <component>
+      <implementation-class>com.intellij.designer.palette.PaletteToolWindowManager</implementation-class>
+    </component>
+  </project-components>
+
+  <extensionPoints>
+    <extensionPoint qualifiedName="Designer.customizations" interface="com.intellij.designer.DesignerCustomizations"/>
+  </extensionPoints>
+</idea-plugin>
diff --git a/plugins/ui-designer-core/src/META-INF/plugin.xml b/plugins/ui-designer-core/src/META-INF/plugin.xml
deleted file mode 100644
index 18d7453..0000000
--- a/plugins/ui-designer-core/src/META-INF/plugin.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<idea-plugin version="2">
-  <name>UI Designer (Core)</name>
-  <id>com.intellij.ui-designer-new</id>
-  <description>
-    Provides shared functionality for visual editing plugins.
-  </description>
-  <vendor>JetBrains</vendor>
-
-  <resource-bundle>messages.DesignerBundle</resource-bundle>
-
-  <depends>com.intellij.modules.lang</depends>
-
-  <project-components>
-    <component>
-      <implementation-class>com.intellij.designer.DesignerToolWindowManager</implementation-class>
-    </component>
-    <component>
-      <implementation-class>com.intellij.designer.palette.PaletteToolWindowManager</implementation-class>
-    </component>
-  </project-components>
-
-  <extensions defaultExtensionNs="com.intellij">
-     <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
-  </extensions>
-
-  <extensionPoints>
-    <extensionPoint qualifiedName="Designer.customizations" interface="com.intellij.designer.DesignerCustomizations"/>
-  </extensionPoints>
-</idea-plugin>
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/DesignerEditor.java b/plugins/ui-designer-core/src/com/intellij/designer/DesignerEditor.java
index 7f29d4e..4aee499 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/DesignerEditor.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/DesignerEditor.java
@@ -73,6 +73,12 @@
     return myDesignerPanel.getPreferredFocusedComponent();
   }
 
+  @NotNull
+  @Override
+  public String getName() {
+    return "Design";
+  }
+
   @Override
   public void dispose() {
     myDesignerPanel.dispose();
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/DragTracker.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/DragTracker.java
index b506ff7..b2eb832 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/DragTracker.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/DragTracker.java
@@ -125,23 +125,26 @@
     myContext.setLocation(getLocation());
 
     if (myContext.getComponents() == null) {
-      List<RadComponent> components = RadComponent.getPureSelection(myArea.getSelection());
-
-      RadComponent parent = null;
-      for (RadComponent component : components) {
-        if (parent == null) {
-          parent = component.getParent();
-        }
-        else if (parent != component.getParent()) {
-          components = Collections.emptyList();
-          break;
-        }
-      }
-
+      List<RadComponent> components = calculateContextComponents(RadComponent.getPureSelection(myArea.getSelection()));
       myContext.setComponents(components);
+
       for (RadComponent component : components) {
         component.processDropOperation(myContext);
       }
     }
   }
+
+  protected List<RadComponent> calculateContextComponents(List<RadComponent> components) {
+    RadComponent parent = null;
+    for (RadComponent component : components) {
+      if (parent == null) {
+        parent = component.getParent();
+      }
+      else if (parent != component.getParent()) {
+        components = Collections.emptyList();
+        break;
+      }
+    }
+    return components;
+  }
 }
\ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/model/MetaManager.java b/plugins/ui-designer-core/src/com/intellij/designer/model/MetaManager.java
index 0727b48..cfa76ef 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/model/MetaManager.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/model/MetaManager.java
@@ -60,19 +60,18 @@
 
     Map<MetaModel, List<String>> modelToMorphing = new HashMap<MetaModel, List<String>>();
 
-    for (Object element : rootElement.getChildren(META)) {
-      loadModel(classLoader, (Element)element, modelToMorphing);
+    for (Element element : rootElement.getChildren(META)) {
+      loadModel(classLoader, element, modelToMorphing);
     }
 
-    for (Object element : rootElement.getChild(PALETTE).getChildren(GROUP)) {
-      loadGroup((Element)element);
+    for (Element element : rootElement.getChild(PALETTE).getChildren(GROUP)) {
+      loadGroup(element);
     }
 
     Element wrapInElement = rootElement.getChild(WRAP_IN);
     if (wrapInElement != null) {
-      for (Object element : wrapInElement.getChildren(ITEM)) {
-        Element item = (Element)element;
-        myWrapModels.add(myTag2Model.get(item.getAttributeValue("tag")));
+      for (Element element : wrapInElement.getChildren(ITEM)) {
+        myWrapModels.add(myTag2Model.get(element.getAttributeValue("tag")));
       }
     }
 
@@ -210,8 +209,7 @@
   protected PaletteGroup loadGroup(Element element) throws Exception {
     PaletteGroup group = createPaletteGroup(element.getAttributeValue(NAME));
 
-    for (Object child : element.getChildren(ITEM)) {
-      Element itemElement = (Element)child;
+    for (Element itemElement : element.getChildren(ITEM)) {
       MetaModel model = getModelByTag(itemElement.getAttributeValue(TAG));
       PaletteItem paletteItem = model.getPaletteItem();
 
@@ -230,8 +228,8 @@
         }
         group.addItem(paletteItem);
 
-        for (Object grandChild : itemElement.getChildren(ITEM)) {
-          group.addItem(createVariationPaletteItem(paletteItem, model, (Element)grandChild));
+        for (Element grandChild : itemElement.getChildren(ITEM)) {
+          group.addItem(createVariationPaletteItem(paletteItem, model, grandChild));
         }
       }
       else {
diff --git a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java
index f2d2b9a..defecc5 100644
--- a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java
+++ b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java
@@ -35,7 +35,6 @@
 import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
 import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
 import org.jetbrains.jps.incremental.*;
-import org.jetbrains.jps.incremental.instrumentation.BaseInstrumentingBuilder;
 import org.jetbrains.jps.incremental.instrumentation.ClassProcessingBuilder;
 import org.jetbrains.jps.incremental.messages.BuildMessage;
 import org.jetbrains.jps.incremental.messages.CompilerMessage;
@@ -123,7 +122,7 @@
       }
     }
     finally {
-      context.processMessage(new ProgressMessage("Finished instrumenting forms [" + chunk.getName() + "]"));
+      context.processMessage(new ProgressMessage("Finished instrumenting forms [" + chunk.getPresentableShortName() + "]"));
     }
 
     return ExitCode.OK;
@@ -197,14 +196,14 @@
       addBinding(compiled.getSourceFile(), formFile, instrumented);
 
       try {
-        context.processMessage(new ProgressMessage("Instrumenting forms... [" + chunk.getName() + "]"));
+        context.processMessage(new ProgressMessage("Instrumenting forms... [" + chunk.getPresentableShortName() + "]"));
 
         final BinaryContent originalContent = compiled.getContent();
         final ClassReader classReader =
           new ClassReader(originalContent.getBuffer(), originalContent.getOffset(), originalContent.getLength());
 
-        final int version = BaseInstrumentingBuilder.getClassFileVersion(classReader);
-        final InstrumenterClassWriter classWriter = new InstrumenterClassWriter(BaseInstrumentingBuilder.getAsmClassWriterFlags(version), finder);
+        final int version = ClassProcessingBuilder.getClassFileVersion(classReader);
+        final InstrumenterClassWriter classWriter = new InstrumenterClassWriter(ClassProcessingBuilder.getAsmClassWriterFlags(version), finder);
         final AsmCodeGenerator codeGenerator = new AsmCodeGenerator(rootContainer, finder, nestedFormsLoader, false, classWriter);
         final byte[] patchedBytes = codeGenerator.patchClass(classReader);
         if (patchedBytes != null) {
diff --git a/plugins/ui-designer/jps-plugin/ui-designer-jps-plugin.iml b/plugins/ui-designer/jps-plugin/ui-designer-jps-plugin.iml
index f466396..70277d7 100644
--- a/plugins/ui-designer/jps-plugin/ui-designer-jps-plugin.iml
+++ b/plugins/ui-designer/jps-plugin/ui-designer-jps-plugin.iml
@@ -16,6 +16,7 @@
     <orderEntry type="module" module-name="instrumentation-util" />
     <orderEntry type="module" module-name="forms-compiler" />
     <orderEntry type="module" module-name="forms_rt" />
+    <orderEntry type="module" module-name="jps-serialization-tests" scope="TEST" />
   </component>
 </module>
 
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java
index 18f2304..c970251 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -55,11 +55,13 @@
     return myDataIndexer;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<String> getKeyDescriptor() {
     return myKeyDescriptor;
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return new DefaultFileTypeSpecificInputFilter(StdFileTypes.GUI_DESIGNER_FORM);
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltSymbolIndex.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltSymbolIndex.java
index 82e218f..f34f0fd 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltSymbolIndex.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltSymbolIndex.java
@@ -132,21 +132,24 @@
         };
     }
 
+    @NotNull
     @Override
     public DataExternalizer<Kind> getValueExternalizer() {
         return new EnumDataDescriptor<Kind>(Kind.class);
     }
 
+    @NotNull
     @Override
     public KeyDescriptor<String> getKeyDescriptor() {
         return new EnumeratorStringDescriptor();
     }
 
+    @NotNull
     @Override
     public FileBasedIndex.InputFilter getInputFilter() {
         return new DefaultFileTypeSpecificInputFilter(StdFileTypes.XML) {
             @Override
-            public boolean acceptInput(VirtualFile file) {
+            public boolean acceptInput(@NotNull VirtualFile file) {
                 return !(file.getFileSystem() instanceof JarFileSystem);
             }
         };
diff --git a/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/impl/XsltStackFrame.java b/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/impl/XsltStackFrame.java
index dfdded1..b8fc055 100644
--- a/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/impl/XsltStackFrame.java
+++ b/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/impl/XsltStackFrame.java
@@ -47,7 +47,7 @@
   }
 
   @Override
-  public void customizePresentation(ColoredTextContainer component) {
+  public void customizePresentation(@NotNull ColoredTextContainer component) {
     if (myDebuggerSession.getCurrentState() == Debugger.State.SUSPENDED) {
       try {
         _customizePresentation(component);
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="&amp;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="&amp;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="&amp;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 &amp;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="&amp;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);
diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties
index 57e0ec1..1a08b7c 100644
--- a/resources-en/src/messages/DebuggerBundle.properties
+++ b/resources-en/src/messages/DebuggerBundle.properties
@@ -320,10 +320,10 @@
 instance.filters.dialog.title=Instance Filters
 instance.filters.dialog.instance.filters.group=Instance Filters
 breakpoint.exception.breakpoint.display.name=''{0}''
-exception.breakpoints.tab.title=Exception Breakpoints
-field.watchpoints.tab.title=Field Watchpoints
-line.breakpoints.tab.title=Line Breakpoints
-method.breakpoints.tab.title=Method Breakpoints
+exception.breakpoints.tab.title=Java Exception Breakpoints
+field.watchpoints.tab.title=Java Field Watchpoints
+line.breakpoints.tab.title=Java Line Breakpoints
+method.breakpoints.tab.title=Java Method Breakpoints
 title.error.evaluating.breakpoint.condition=Breakpoint Condition Error
 title.error.evaluating.breakpoint.action=Breakpoint Action Error
 error.evaluating.breakpoint.condition.or.action=Problem processing VM event:\nBreakpoint: ''{0}''\nError: {1}\nWould you like to stop at the breakpoint?
@@ -446,5 +446,3 @@
 action.kill.process.text=Kill Process
 action.kill.process.description=Forcibly terminate debugged application
 evaluation.error.unknown.method.return.type=Cannot resolve method return type: {0}
-
-java.breakpoint.title=Java Line Breakpoints
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index d04e059..ff39c26 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -86,9 +86,6 @@
     <extensionPoint name="debugger.nodeRenderer"
                     interface="com.intellij.debugger.ui.tree.render.NodeRenderer"/>
 
-    <extensionPoint name="debugger.breakpointFactory"
-                    interface="com.intellij.debugger.ui.breakpoints.BreakpointFactory"/>
-
     <extensionPoint name="debugger.jvmDebugProvider"
                     interface="com.intellij.debugger.engine.JVMDebugProvider"/>
 
@@ -627,7 +624,7 @@
                      groupName="Java language level migration aids" enabledByDefault="true" level="WARNING"
                      implementationClass="com.intellij.codeInspection.AnonymousCanBeLambdaInspection" />
     <localInspection language="JAVA" shortName="Convert2streamapi" displayName="foreach loop can be collapsed with stream api"
-                     groupName="Java language level migration aids" enabledByDefault="true" level="WARNING" implementationClass="com.intellij.codeInspection.StreamApiMigrationInspection"/>
+                     groupName="Java language level migration aids" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.intellij.codeInspection.StreamApiMigrationInspection"/>
     <localInspection language="JAVA" shortName="Anonymous2MethodRef" displayName="Anonymous type can be replaced with method reference"
                      groupName="Java language level migration aids" enabledByDefault="true" level="WARNING"
                      implementationClass="com.intellij.codeInspection.AnonymousCanBeMethodReferenceInspection" />
@@ -1378,11 +1375,11 @@
     <resolveScopeEnlarger implementation="com.intellij.psi.NonClasspathResolveScopeEnlarger"/>
 
     <xdebugger.debuggerSupport implementation="com.intellij.debugger.ui.JavaDebuggerSupport"/>
-    <debugger.breakpointFactory implementation="com.intellij.debugger.ui.breakpoints.LineBreakpointFactory"/>
-    <debugger.breakpointFactory implementation="com.intellij.debugger.ui.breakpoints.ExceptionBreakpointFactory"/>
-    <debugger.breakpointFactory implementation="com.intellij.debugger.ui.breakpoints.AnyExceptionBreakpointFactory"/>
-    <debugger.breakpointFactory implementation="com.intellij.debugger.ui.breakpoints.FieldBreakpointFactory"/>
-    <debugger.breakpointFactory implementation="com.intellij.debugger.ui.breakpoints.MethodBreakpointFactory"/>
+    <xdebugger.breakpointType implementation="com.intellij.debugger.ui.breakpoints.JavaMethodBreakpointType"/>
+    <xdebugger.breakpointType implementation="com.intellij.debugger.ui.breakpoints.JavaWildcardMethodBreakpointType"/>
+    <xdebugger.breakpointType implementation="com.intellij.debugger.ui.breakpoints.JavaFieldBreakpointType"/>
+    <xdebugger.breakpointType implementation="com.intellij.debugger.ui.breakpoints.JavaExceptionBreakpointType"/>
+    <xdebugger.breakpointType implementation="com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType"/>
     <debugger.jvmSmartStepIntoHandler implementation="com.intellij.debugger.actions.JavaSmartStepIntoHandler"/>
 
     <applicationService serviceInterface="com.intellij.remoteServer.runtime.deployment.debug.JavaDebuggerLauncher"
@@ -1461,8 +1458,6 @@
 
     <codeInsight.unresolvedReferenceQuickFixProvider implementation="com.intellij.jarFinder.FindJarQuickFixProvider"/>
 
-    <xdebugger.breakpointType implementation="org.jetbrains.java.debugger.breakpoints.JavaBreakpointType"/>
-
     <refactoring.pullUpHelperFactory language="JAVA" implementationClass="com.intellij.refactoring.memberPullUp.JavaPullUpHelperFactory"/>
     <hierarchy.referenceProcessor implementation="com.intellij.ide.hierarchy.call.JavaCallReferenceProcessor"/>
     <projectTemplate projectType="JAVA_MODULE" templatePath="resources/projectTemplates/Java/Command_Line_App.zip"/>
diff --git a/spellchecker/src/com/intellij/spellchecker/english.dic b/spellchecker/src/com/intellij/spellchecker/english.dic
index 169e4c2..0047044 100644
--- a/spellchecker/src/com/intellij/spellchecker/english.dic
+++ b/spellchecker/src/com/intellij/spellchecker/english.dic
@@ -68545,6 +68545,7 @@
 fundraiser
 fundraisers
 funds
+fundraising
 funeral
 funeral's
 funerals
diff --git a/updater/src/com/intellij/updater/Runner.java b/updater/src/com/intellij/updater/Runner.java
index 966a4a0..1e57010 100644
--- a/updater/src/com/intellij/updater/Runner.java
+++ b/updater/src/com/intellij/updater/Runner.java
@@ -24,15 +24,13 @@
   private static final String NEW_BUILD_DESCRIPTION = "new.build.description";
 
   public static void main(String[] args) throws Exception {
-    if (args.length >= 7 && "create".equals(args[0])) {
+    if (args.length >= 6 && "create".equals(args[0])) {
       String oldVersionDesc = args[1];
       String newVersionDesc = args[2];
       String oldFolder = args[3];
       String newFolder = args[4];
       String patchFile = args[5];
-
-      String logFolder = args[6];
-      initLogger(logFolder);
+      initLogger();
 
       List<String> ignoredFiles = extractFiles(args, "ignored");
       List<String> criticalFiles = extractFiles(args, "critical");
@@ -41,9 +39,7 @@
     }
     else if (args.length >= 2 && "install".equals(args[0])) {
       String destFolder = args[1];
-
-      String logFolder = args.length >= 3 ? args[2] : null;
-      initLogger(logFolder);
+      initLogger();
       logger.info("destFolder: " + destFolder);
 
       install(destFolder);
@@ -59,7 +55,8 @@
     return fileLogDir.isDirectory() && fileLogDir.canWrite() && fileLogDir.getUsableSpace() >= 1000000;
   }
 
-  private static String getLogDir(String logFolder) {
+  private static String getLogDir() {
+    String logFolder = System.getProperty("idea.updater.log");
     if (logFolder == null || !isValidLogDir(logFolder)) {
       logFolder = System.getProperty("java.io.tmpdir");
       if (!isValidLogDir(logFolder)) {
@@ -69,9 +66,9 @@
     return logFolder;
   }
 
-  public static void initLogger(String logFolder) {
+  public static void initLogger() {
     if (logger == null) {
-      logFolder = getLogDir(logFolder);
+      String logFolder = getLogDir();
       FileAppender update = new FileAppender();
 
       update.setFile(new File(logFolder, "idea_updater.log").getAbsolutePath());
@@ -84,7 +81,6 @@
       updateError.setFile(new File(logFolder, "idea_updater_error.log").getAbsolutePath());
       updateError.setLayout(new PatternLayout("%d{dd MMM yyyy HH:mm:ss} %-5p %C{1}.%M - %m%n"));
       updateError.setThreshold(Level.ERROR);
-      // The error(s) from an old run of the updater (if there were) could be found in idea_updater.log file
       updateError.setAppend(false);
       updateError.activateOptions();
 
@@ -200,17 +196,20 @@
       in.close();
     }
 
-    SwingUtilities.invokeAndWait(new Runnable() {
-      @Override
-      public void run() {
-        try {
-          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+    // todo[r.sh] to delete in IDEA 14 (after a full circle of platform updates)
+    if (System.getProperty("swing.defaultlaf") == null) {
+      SwingUtilities.invokeAndWait(new Runnable() {
+        @Override
+        public void run() {
+          try {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+          }
+          catch (Exception ignore) {
+            printStackTrace(ignore);
+          }
         }
-        catch (Exception ignore) {
-          printStackTrace(ignore);
-        }
-      }
-    });
+      });
+    }
 
     new SwingUpdaterUI(props.getProperty(OLD_BUILD_DESCRIPTION),
                   props.getProperty(NEW_BUILD_DESCRIPTION),
diff --git a/updater/testSrc/com/intellij/updater/DigesterTest.java b/updater/testSrc/com/intellij/updater/DigesterTest.java
index a7ec965..3b524f8 100644
--- a/updater/testSrc/com/intellij/updater/DigesterTest.java
+++ b/updater/testSrc/com/intellij/updater/DigesterTest.java
@@ -10,12 +10,12 @@
 public class DigesterTest extends UpdaterTestCase {
   @Test
   public void testBasics() throws Exception {
+    Runner.initLogger();
     Map<String, Long> checkSums = Digester.digestFiles(getDataDir(), Collections.<String>emptyList(), TEST_UI);
     assertEquals(12, checkSums.size());
 
     assertEquals(CHECKSUMS.README_TXT, (long)checkSums.get("Readme.txt"));
     assertEquals(CHECKSUMS.FOCUSKILLER_DLL, (long)checkSums.get("bin/focuskiller.dll"));
     assertEquals(CHECKSUMS.BOOTSTRAP_JAR, (long)checkSums.get("lib/bootstrap.jar"));
-    Runner.initLogger(System.getProperty("java.io.tmpdir"));
   }
 }
\ No newline at end of file
diff --git a/updater/testSrc/com/intellij/updater/RunnerTest.java b/updater/testSrc/com/intellij/updater/RunnerTest.java
index 4813db1..22464a0 100644
--- a/updater/testSrc/com/intellij/updater/RunnerTest.java
+++ b/updater/testSrc/com/intellij/updater/RunnerTest.java
@@ -11,7 +11,7 @@
   @Test
   public void testExtractingFiles() throws Exception {
     String[] args = {"bar", "ignored=xxx;yyy;zzz/zzz", "critical=", "ignored=aaa", "baz", "critical=ccc"};
-    Runner.initLogger(System.getProperty("java.io.tmpdir"));
+    Runner.initLogger();
 
     assertEquals(Arrays.asList("xxx", "yyy", "zzz/zzz", "aaa"),
                  Runner.extractFiles(args, "ignored"));
diff --git a/updater/testSrc/com/intellij/updater/UpdaterTestCase.java b/updater/testSrc/com/intellij/updater/UpdaterTestCase.java
index 82d7bbe..dea5fbd 100644
--- a/updater/testSrc/com/intellij/updater/UpdaterTestCase.java
+++ b/updater/testSrc/com/intellij/updater/UpdaterTestCase.java
@@ -25,7 +25,7 @@
 
   @Before
   public void setUp() throws Exception {
-    Runner.initLogger(System.getProperty("java.io.tmpdir"));
+    Runner.initLogger();
     myTempDirFixture = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture();
     myTempDirFixture.setUp();
 
diff --git a/xml/dom-impl/src/com/intellij/util/xml/DomFileIndex.java b/xml/dom-impl/src/com/intellij/util/xml/DomFileIndex.java
index 493f6a5..7ca36a6 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/DomFileIndex.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/DomFileIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -84,11 +84,13 @@
     return myDataIndexer;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<String> getKeyDescriptor() {
     return new EnumeratorStringDescriptor();
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return new DefaultFileTypeSpecificInputFilter(StdFileTypes.XML);
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomApplicationComponent.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomApplicationComponent.java
index f995670..c2687fd 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomApplicationComponent.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomApplicationComponent.java
@@ -96,8 +96,10 @@
   public int getCumulativeVersion() {
     int result = 0;
     for (DomFileDescription description : getAllFileDescriptions()) {
-      result += description.getVersion();
-      result += description.getRootTagName().hashCode(); // so that a plugin enabling/disabling could trigger the reindexing
+      if (description.hasStubs()) {
+        result += description.getStubVersion();
+        result += description.getRootTagName().hashCode(); // so that a plugin enabling/disabling could trigger the reindexing
+      }
     }
     return result;
   }
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
index 4249986..8446e88 100644
--- a/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
+++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlCompletionData.java
@@ -218,8 +218,9 @@
           containingFile = (XmlFile)document.getContainingFile();
 
           final FileType ft = containingFile.getFileType();
-
-          if(ft != StdFileTypes.XML) {
+          if (HtmlUtil.isHtml5Document(document)) {
+            descriptorFile = XmlUtil.findXmlFile(containingFile, Html5SchemaProvider.getCharsDtdLocation());
+          } else if(ft != StdFileTypes.XML) {
             final String namespace = ft == StdFileTypes.XHTML || ft == StdFileTypes.JSPX ? XmlUtil.XHTML_URI : XmlUtil.HTML_URI;
             final XmlNSDescriptor nsDescriptor = document.getDefaultNSDescriptor(namespace, true);
 
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.java b/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.java
index e724f7b..be90356 100644
--- a/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.java
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.java
@@ -32,6 +32,7 @@
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.highlighter.EditorHighlighter;
 import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.UnfairTextRange;
 import com.intellij.psi.FileViewProvider;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
@@ -107,8 +108,8 @@
       final ASTNode tagStartEnd = XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode());
       final ASTNode tagEndStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(tag.getNode());
       if (tagStartEnd != null && tagEndStart != null) {
-        result.add(new TextRange(tagStartEnd.getTextRange().getEndOffset(),
-                                 tagEndStart.getTextRange().getStartOffset()));
+        result.add(new UnfairTextRange(tagStartEnd.getTextRange().getEndOffset(),
+                                       tagEndStart.getTextRange().getStartOffset()));
       }
       if (tagStartEnd != null) {
         result.add(new TextRange(tag.getTextRange().getStartOffset(),
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlEqTypedHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlEqTypedHandler.java
index 922d910..e483f34 100644
--- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlEqTypedHandler.java
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlEqTypedHandler.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.
@@ -18,31 +18,34 @@
 import com.intellij.application.options.editor.WebEditorOptions;
 import com.intellij.codeInsight.AutoPopupController;
 import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.editor.Caret;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.List;
+
 public class XmlEqTypedHandler extends TypedHandlerDelegate {
-  private boolean needToInsertQuotes = false;
+  private List<Caret> caretsForInsertingQuotes = ContainerUtil.newSmartList();
 
   @Override
-  public Result beforeCharTyped(char c,
-                                Project project,
-                                Editor editor,
-                                PsiFile file,
-                                FileType fileType) {
+  public Result beforeCharTyped(char c, Project project, Editor editor, PsiFile file, FileType fileType) {
 
     if (WebEditorOptions.getInstance().isInsertQuotesForAttributeValue()) {
       boolean inXml = file.getLanguage() instanceof XMLLanguage || file.getViewProvider().getBaseLanguage() instanceof XMLLanguage;
       if (c == '=' && inXml) {
-        int offset = editor.getCaretModel().getOffset();
-        PsiElement at = file.findElementAt(offset - 1);
-        PsiElement atParent = at != null ? at.getParent() : null;
-        needToInsertQuotes = atParent instanceof XmlAttribute && ((XmlAttribute)atParent).getValueElement() == null;
+        for(Caret caret : editor.getCaretModel().getAllCarets()) {
+          PsiElement at = file.findElementAt(caret.getOffset() - 1);
+          PsiElement atParent = at != null ? at.getParent() : null;
+          if(atParent instanceof XmlAttribute && ((XmlAttribute)atParent).getValueElement() == null) {
+            caretsForInsertingQuotes.add(caret);
+          }
+        }
       }
     }
 
@@ -51,13 +54,14 @@
 
   @Override
   public Result charTyped(char c, Project project, @NotNull Editor editor, @NotNull PsiFile file) {
-    if (needToInsertQuotes) {
-      int offset = editor.getCaretModel().getOffset();
-      editor.getDocument().insertString(offset, "\"\"");
-      editor.getCaretModel().moveToOffset(offset + 1);
+    for (Caret caret : caretsForInsertingQuotes) {
+      editor.getDocument().insertString(caret.getOffset(), "\"\"");
+      caret.moveCaretRelatively(1, 0, false, true);
+    }
+    if (editor.getCaretModel().getAllCarets().size() == caretsForInsertingQuotes.size()) {
       AutoPopupController.getInstance(project).scheduleAutoPopup(editor);
     }
-    needToInsertQuotes = false;
+    caretsForInsertingQuotes.clear();
     return super.charTyped(c, project, editor, file);
   }
 }
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java
index e76b5a3..fcebe19 100644
--- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -20,7 +20,9 @@
 import com.intellij.lang.ASTNode;
 import com.intellij.lang.xml.XMLLanguage;
 import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Caret;
 import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorModificationUtil;
 import com.intellij.openapi.editor.ScrollType;
 import com.intellij.openapi.editor.ex.EditorEx;
 import com.intellij.openapi.editor.highlighter.HighlighterIterator;
@@ -37,12 +39,15 @@
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.xml.*;
 import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.xml.XmlElementDescriptor;
 import com.intellij.xml.XmlElementDescriptorWithCDataContent;
 import com.intellij.xml.util.HtmlUtil;
 import com.intellij.xml.util.XmlUtil;
 import org.jetbrains.annotations.NonNls;
 
+import java.util.Collection;
+
 public class XmlGtTypedHandler extends TypedHandlerDelegate {
   private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.editorActions.TypedHandler");
 
@@ -88,9 +93,8 @@
             }
 
             if (tokenType == XmlTokenType.XML_TAG_END ||
-                tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END && element.getTextOffset() == offset - 1
-               ) {
-              editor.getCaretModel().moveToOffset(offset + 1);
+                tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END && element.getTextOffset() == offset - 1) {
+              EditorModificationUtil.moveAllCaretsRelatively(editor, 1);
               editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
               return Result.STOP;
             }
@@ -149,10 +153,9 @@
       if (!(element instanceof XmlTag)) {
         if (element instanceof XmlTokenImpl &&
             element.getPrevSibling() !=null &&
-            element.getPrevSibling().getText().equals("<")
-           ) {
+            element.getPrevSibling().getText().equals("<")) {
           // tag is started and there is another text in the end
-          editor.getDocument().insertString(offset, "</" + element.getText() + ">");
+          EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, "</" + element.getText() + ">", false, 0);
         }
         return Result.CONTINUE;
       }
@@ -230,36 +233,38 @@
         if (hasBalance) return Result.CONTINUE; 
       }
 
-      TextRange cdataReformatRange = null;
+      Collection<TextRange> cdataReformatRanges = null;
       final XmlElementDescriptor descriptor = tag.getDescriptor();
 
       if (descriptor instanceof XmlElementDescriptorWithCDataContent) {
         final XmlElementDescriptorWithCDataContent cDataContainer = (XmlElementDescriptorWithCDataContent)descriptor;
 
+        cdataReformatRanges = ContainerUtil.newSmartList();
         if (cDataContainer.requiresCdataBracesInContext(tag)) {
-          int rangeStart = offset;
           @NonNls final String cDataStart = "><![CDATA[";
           final String inserted = cDataStart + "\n]]>";
-          editor.getDocument().insertString(offset, inserted);
-          final int newoffset = offset + cDataStart.length();
-          editor.getCaretModel().moveToOffset(newoffset);
-          offset += inserted.length();
-          cdataReformatRange = new TextRange(rangeStart, offset + 1);
+          EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, inserted, false, cDataStart.length());
+          for (Caret caret : editor.getCaretModel().getAllCarets()) {
+            int caretOffset = caret.getOffset();
+            if (caretOffset >= cDataStart.length()) {
+              cdataReformatRanges.add(TextRange.from(caretOffset - cDataStart.length(), inserted.length()));
+            }
+          }
         }
       }
 
-      editor.getDocument().insertString(offset, "</" + name + ">");
+      EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, "</" + name + ">", false, 0);
 
-      if (cdataReformatRange != null) {
+      if (cdataReformatRanges != null && !cdataReformatRanges.isEmpty()) {
         PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
         try {          
-          CodeStyleManager.getInstance(project).reformatText(file, cdataReformatRange.getStartOffset(), cdataReformatRange.getEndOffset());
+          CodeStyleManager.getInstance(project).reformatText(file, cdataReformatRanges);
         }
         catch (IncorrectOperationException e) {
           LOG.error(e);
         }
       }
-      return cdataReformatRange != null ? Result.STOP : Result.CONTINUE;
+      return cdataReformatRanges != null && !cdataReformatRanges.isEmpty() ? Result.STOP : Result.CONTINUE;
     }
     return Result.CONTINUE;
   }
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java
index 35e7727..9824d44 100644
--- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -39,6 +39,7 @@
 
       PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
       final int offset = editor.getCaretModel().getOffset();
+      if (file == null) return Result.CONTINUE;
       FileViewProvider provider = file.getViewProvider();
       PsiElement element = provider.findElementAt(offset, XMLLanguage.class);
 
@@ -71,6 +72,7 @@
       PsiDocumentManager.getInstance(project).commitAllDocuments();
 
       PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+      if (file == null) return Result.CONTINUE;
       FileViewProvider provider = file.getViewProvider();
       final int offset = editor.getCaretModel().getOffset();
       PsiElement element = provider.findElementAt(offset - 1, XMLLanguage.class);
@@ -91,7 +93,7 @@
               tag = tag1;
             }
           }
-          EditorModificationUtil.insertStringAtCaret(editor, tag.getName() + ">");
+          EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, tag.getName() + ">", false);
           return Result.STOP;
         }
       }
@@ -100,7 +102,7 @@
       while((prevLeaf = TreeUtil.prevLeaf(prevLeaf)) != null && prevLeaf.getElementType() == XmlTokenType.XML_WHITE_SPACE);
       if(prevLeaf instanceof OuterLanguageElement) {
         element = file.getViewProvider().findElementAt(offset - 1, file.getLanguage());
-        prevLeaf = element.getNode();
+        prevLeaf = element != null ? element.getNode() : null;
         while((prevLeaf = TreeUtil.prevLeaf(prevLeaf)) != null && prevLeaf.getElementType() == XmlTokenType.XML_WHITE_SPACE);
       }
       if(prevLeaf == null) return Result.CONTINUE;
@@ -118,7 +120,7 @@
       if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null) return Result.CONTINUE;
       if (PsiTreeUtil.getParentOfType(element, XmlAttributeValue.class) != null) return Result.CONTINUE;
 
-      EditorModificationUtil.insertStringAtCaret(editor, ">");
+      EditorModificationUtil.typeInStringAtCaretHonorMultipleCarets(editor, ">", false);
       return Result.STOP;
     }
     return Result.CONTINUE;
diff --git a/xml/impl/src/com/intellij/html/index/Html5CustomAttributesIndex.java b/xml/impl/src/com/intellij/html/index/Html5CustomAttributesIndex.java
index ed0538b..984bd49 100644
--- a/xml/impl/src/com/intellij/html/index/Html5CustomAttributesIndex.java
+++ b/xml/impl/src/com/intellij/html/index/Html5CustomAttributesIndex.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.
@@ -86,16 +86,18 @@
     return myIndexer;
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<String> getKeyDescriptor() {
     return new EnumeratorStringDescriptor();
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return new DefaultFileTypeSpecificInputFilter(StdFileTypes.HTML, StdFileTypes.XHTML) {
       @Override
-      public boolean acceptInput(final VirtualFile file) {
+      public boolean acceptInput(@NotNull final VirtualFile file) {
         return file.isInLocalFileSystem();
       }
     };
diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java
index cd62adf..1b2fabd 100644
--- a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java
+++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -26,6 +26,7 @@
 import com.intellij.openapi.editor.LogicalPosition;
 import com.intellij.openapi.editor.ScrollType;
 import com.intellij.openapi.editor.colors.EditorFontType;
+import com.intellij.openapi.editor.event.CaretAdapter;
 import com.intellij.openapi.editor.event.CaretEvent;
 import com.intellij.openapi.editor.event.CaretListener;
 import com.intellij.openapi.extensions.Extensions;
@@ -103,7 +104,7 @@
 
     myInfoProvider = findInfoProvider(findViewProvider(myFile, myProject));
 
-    final CaretListener caretListener = new CaretListener() {
+    final CaretListener caretListener = new CaretAdapter() {
       public void caretPositionChanged(final CaretEvent e) {
         if (myUserCaretChange) {
           queueUpdate(editor);
diff --git a/xml/impl/src/com/intellij/xml/index/SchemaTypeInheritanceIndex.java b/xml/impl/src/com/intellij/xml/index/SchemaTypeInheritanceIndex.java
index 5155221..f504b66 100644
--- a/xml/impl/src/com/intellij/xml/index/SchemaTypeInheritanceIndex.java
+++ b/xml/impl/src/com/intellij/xml/index/SchemaTypeInheritanceIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -133,11 +133,12 @@
     };
   }
 
+  @NotNull
   @Override
   public DataExternalizer<Set<SchemaTypeInfo>> getValueExternalizer() {
     return new DataExternalizer<Set<SchemaTypeInfo>>() {
       @Override
-      public void save(DataOutput out, Set<SchemaTypeInfo> value) throws IOException {
+      public void save(@NotNull DataOutput out, Set<SchemaTypeInfo> value) throws IOException {
         out.writeInt(value.size());
         for (SchemaTypeInfo key : value) {
           out.writeUTF(key.getNamespaceUri());
@@ -147,7 +148,7 @@
       }
 
       @Override
-      public Set<SchemaTypeInfo> read(DataInput in) throws IOException {
+      public Set<SchemaTypeInfo> read(@NotNull DataInput in) throws IOException {
         final Set<SchemaTypeInfo> set = new HashSet<SchemaTypeInfo>();
         final int size = in.readInt();
         for (int i = 0; i < size; i++) {
diff --git a/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java b/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java
index 97fb7c0..b3fc55c 100644
--- a/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java
+++ b/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -70,6 +70,7 @@
     };
   }
 
+  @NotNull
   @Override
   public DataExternalizer<Void> getValueExternalizer() {
     return ScalarIndexExtension.VOID_DATA_EXTERNALIZER;
diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/model/resolve/RelaxSymbolIndex.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/model/resolve/RelaxSymbolIndex.java
index eede27a..a00d40d 100644
--- a/xml/relaxng/src/org/intellij/plugins/relaxNG/model/resolve/RelaxSymbolIndex.java
+++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/model/resolve/RelaxSymbolIndex.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ * 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 org.intellij.plugins.relaxNG.model.resolve;
 
 import com.intellij.ide.highlighter.XmlFileType;
@@ -129,16 +144,18 @@
     };
   }
 
+  @NotNull
   @Override
   public KeyDescriptor<String> getKeyDescriptor() {
     return new EnumeratorStringDescriptor();
   }
 
+  @NotNull
   @Override
   public FileBasedIndex.InputFilter getInputFilter() {
     return new DefaultFileTypeSpecificInputFilter(StdFileTypes.XML, RncFileType.getInstance()) {
       @Override
-      public boolean acceptInput(VirtualFile file) {
+      public boolean acceptInput(@NotNull VirtualFile file) {
         return !(file.getFileSystem() instanceof JarFileSystem);
       }
     };
diff --git a/xml/tests/src/com/intellij/codeInsight/completion/XmlTypedHandlersTest.java b/xml/tests/src/com/intellij/codeInsight/completion/XmlTypedHandlersTest.java
index 6c4b73f..93967d2 100644
--- a/xml/tests/src/com/intellij/codeInsight/completion/XmlTypedHandlersTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/completion/XmlTypedHandlersTest.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.
@@ -17,6 +17,7 @@
 
 import com.intellij.application.options.editor.WebEditorOptions;
 import com.intellij.ide.highlighter.XmlFileType;
+import com.intellij.testFramework.EditorTestUtil;
 import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
 
 /**
@@ -24,16 +25,75 @@
  *         Date: 30.08.13
  */
 public class XmlTypedHandlersTest extends LightPlatformCodeInsightFixtureTestCase {
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    EditorTestUtil.enableMultipleCarets();
+  }
 
-  public void testClosingTag() throws Exception {
+  @Override
+  protected void tearDown() throws Exception {
+    EditorTestUtil.disableMultipleCarets();
+    super.tearDown();
+  }
+
+  public void testClosingTag() {
     doTest("<foo><<caret>", '/', "<foo></foo>");
   }
 
+  public void testValueQuotesWithMultiCarets() {
+    doTest("<foo bar<caret>><foo bar<caret>>", '=', "<foo bar=\"<caret>\"><foo bar=\"<caret>\">");
+  }
+
+  public void testValueQuotesWithMultiCaretsWithDifferentContexts() {
+    doTest("<foo bar <caret>><foo bar<caret>>", '=', "<foo bar =<caret>><foo bar=\"<caret>\">");
+  }
+
+  public void testCloseTagOnSlashWithMultiCarets() {
+    doTest("<bar>\n" +
+           "<foo><<caret>\n" +
+           "<foo><<caret>\n" +
+           "</bar>", '/', "<bar>\n" +
+                          "<foo></foo><caret>\n" +
+                          "<foo></foo><caret>\n" +
+                          "</bar>");
+  }
+
+  public void testCloseTagOnGtWithMultiCarets() {
+    doTest("<bar>\n" +
+           "<foo<caret>\n" +
+           "<foo<caret>\n" +
+           "</bar>", '>', "<bar>\n" +
+                          "<foo><caret></foo>\n" +
+                          "<foo><caret></foo>\n" +
+                          "</bar>");
+  }
+
+  public void _testCloseTagOnSlashWithMultiCaretsInDifferentContexts() {
+    doTest("<bar>\n" +
+           "<foo><<caret>\n" +
+           "<fiz><<caret>\n" +
+           "</bar>", '/', "<bar>\n" +
+                          "<foo></foo><caret>\n" +
+                          "<fiz></fiz><caret>\n" +
+                          "</bar>");
+  }
+
+  public void _testCloseTagOnGtWithMultiCaretsInDifferentContexts() {
+    doTest("<bar>\n" +
+           "<foo<caret>\n" +
+           "<fiz<caret>\n" +
+           "</bar>", '>', "<bar>\n" +
+                          "<foo><caret></foo>\n" +
+                          "<fiz><caret></fiz>\n" +
+                          "</bar>");
+  }
+
   public void testGreedyClosing() {
     doTest("<foo><<caret>foo>", '/', "<foo></foo>");
   }
 
-  public void testValueQuotas() throws Exception {
+  public void testValueQuotas() {
     doTest("<foo bar<caret>", '=', "<foo bar=\"<caret>\"");
     WebEditorOptions.getInstance().setInsertQuotesForAttributeValue(false);
     try {
diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java b/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java
index 4d58a55..d5bec52 100644
--- a/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java
@@ -514,18 +514,23 @@
       if (classLoader == null && clazz == null) return file;
 
       final URL resource = clazz == null ? classLoader.getResource(file) : clazz.getResource(file);
-      classLoader = null;
-      clazz = null;
-      if (resource == null) {
-        String message = "Cannot find standard resource. filename:" + file + " class=" + classLoader;
-        if (ApplicationManager.getApplication().isUnitTestMode()) {
-          LOG.error(message);
-        }
-        else {
-          LOG.warn(message);
-        }
 
-        return null;
+      try {
+        if (resource == null) {
+          String message = "Cannot find standard resource. filename:" + file + " class=" + clazz + ", classLoader:" + classLoader;
+          if (ApplicationManager.getApplication().isUnitTestMode()) {
+            LOG.error(message);
+          }
+          else {
+            LOG.warn(message);
+          }
+
+          return null;
+        }
+      }
+      finally {
+        classLoader = null;
+        clazz = null;
       }
 
       String path = FileUtil.unquote(resource.toString());
@@ -535,7 +540,6 @@
       return path;
     }
 
-
     @Override
     public boolean equals(Object o) {
       if (this == o) return true;
diff --git a/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java b/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java
index 250d27e..55ab6d2 100644
--- a/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java
+++ b/xml/xml-psi-impl/src/com/intellij/lang/html/HtmlParsing.java
@@ -76,7 +76,10 @@
         error = flushError(error);
         parseProcessingInstruction();
       }
-      else if (tt == XmlTokenType.XML_REAL_WHITE_SPACE || tt == XmlTokenType.XML_CHAR_ENTITY_REF || tt == XmlTokenType.XML_DATA_CHARACTERS) {
+      else if (tt == XmlTokenType.XML_CHAR_ENTITY_REF || tt == XmlTokenType.XML_ENTITY_REF_TOKEN) {
+        parseReference();
+      }
+      else if (tt == XmlTokenType.XML_REAL_WHITE_SPACE || tt == XmlTokenType.XML_DATA_CHARACTERS) {
         error = flushError(error);
         advance();
       } else if (tt == XmlTokenType.XML_END_TAG_START) {
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java
index e666cdc..8bd3997 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java
@@ -152,27 +152,28 @@
          ) {
         XmlDocument document = ((XmlFile)targetElement).getDocument();
         final XmlTag rootTag = document.getRootTag();
+        XmlFile descriptorFile = null;
 
-        if (rootTag != null && document.getUserData(DISABLE_ENTITY_EXPAND) == null) {
+        if (HtmlUtil.isHtml5Document(document)) {
+          descriptorFile = XmlUtil.findXmlFile((XmlFile)targetElement, Html5SchemaProvider.getCharsDtdLocation());
+        } else if (rootTag != null && document.getUserData(DISABLE_ENTITY_EXPAND) == null) {
           final XmlElementDescriptor descriptor = rootTag.getDescriptor();
 
             if (descriptor != null && !(descriptor instanceof AnyXmlElementDescriptor)) {
-              PsiElement element = !HtmlUtil.isHtml5Context(rootTag) ? descriptor.getDeclaration() :
-                                   XmlUtil.findXmlFile((XmlFile)targetElement, Html5SchemaProvider.getCharsDtdLocation());
+              PsiElement element = descriptor.getDeclaration();
               final PsiFile containingFile = element != null ? element.getContainingFile():null;
-              final XmlFile descriptorFile = containingFile instanceof XmlFile ? (XmlFile)containingFile:null;
-
-              if (descriptorFile != null &&
-                  !descriptorFile.getName().equals(((XmlFile)targetElement).getName()+".dtd")) {
-                deps.add(descriptorFile);
-                XmlUtil.processXmlElements(
-                  descriptorFile,
-                  processor,
-                  true
-                );
-              }
+              descriptorFile = containingFile instanceof XmlFile ? (XmlFile)containingFile:null;
             }
         }
+        if (descriptorFile != null &&
+            !descriptorFile.getName().equals(((XmlFile)targetElement).getName() + ".dtd")) {
+          deps.add(descriptorFile);
+          XmlUtil.processXmlElements(
+            descriptorFile,
+            processor,
+            true
+          );
+        }
       }
 
       return new CachedValueProvider.Result<XmlEntityDecl>(result[0], ArrayUtil.toObjectArray(deps));
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
index 36ae151..5d35f0f 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java
@@ -325,7 +325,11 @@
                   final CachedValue<XmlAttributeDescriptor> value = CachedValuesManager.getManager(includedDocument.getProject()).createCachedValue(
                     new CachedValueProvider<XmlAttributeDescriptor>(){
                       public Result<XmlAttributeDescriptor> compute() {
-                        return new Result<XmlAttributeDescriptor>(attributeDescriptor, attributeDescriptor.getDependences());
+                        Object[] deps = attributeDescriptor.getDependences();
+                        if (deps.length == 0) {
+                          LOG.error(attributeDescriptor + " returned no dependencies");
+                        }
+                        return new Result<XmlAttributeDescriptor>(attributeDescriptor, deps);
                       }
                     },
                     false
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/index/XmlIndex.java b/xml/xml-psi-impl/src/com/intellij/xml/index/XmlIndex.java
index 1e54944..fb5242c 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/index/XmlIndex.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/index/XmlIndex.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.
@@ -95,13 +95,15 @@
     };
   }
 
+  @NotNull
   public KeyDescriptor<String> getKeyDescriptor() {
     return KEY_DESCRIPTOR;
   }
 
+  @NotNull
   public FileBasedIndex.InputFilter getInputFilter() {
     return new DefaultFileTypeSpecificInputFilter(XmlFileType.INSTANCE, DTDFileType.INSTANCE) {
-      public boolean acceptInput(final VirtualFile file) {
+      public boolean acceptInput(@NotNull final VirtualFile file) {
         FileType fileType = file.getFileType();
         final String extension = file.getExtension();
         return XmlFileType.INSTANCE.equals(fileType) && "xsd".equals(extension) ||
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/index/XmlNamespaceIndex.java b/xml/xml-psi-impl/src/com/intellij/xml/index/XmlNamespaceIndex.java
index 55cde70..923a5cf 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/index/XmlNamespaceIndex.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/index/XmlNamespaceIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 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.
@@ -107,11 +107,12 @@
     };
   }
 
+  @NotNull
   @Override
   public DataExternalizer<XsdNamespaceBuilder> getValueExternalizer() {
     return new DataExternalizer<XsdNamespaceBuilder>() {
       @Override
-      public void save(DataOutput out, XsdNamespaceBuilder value) throws IOException {
+      public void save(@NotNull DataOutput out, XsdNamespaceBuilder value) throws IOException {
         out.writeUTF(value.getNamespace() == null ? "" : value.getNamespace());
         out.writeUTF(value.getVersion() == null ? "" : value.getVersion());
         out.writeInt(value.getTags().size());
@@ -121,7 +122,7 @@
       }
 
       @Override
-      public XsdNamespaceBuilder read(DataInput in) throws IOException {
+      public XsdNamespaceBuilder read(@NotNull DataInput in) throws IOException {
 
         int count;
         XsdNamespaceBuilder builder = new XsdNamespaceBuilder(in.readUTF(), in.readUTF(), new ArrayList<String>(count = in.readInt()));